WindowsAPI每日一练(2) 使用应用程序句柄

WindowsAPI每日一练系列 :https://www.cnblogs.com/LexMoon/category/1246238.html
  WindowsAPI每日一练(1) WinMain
  WindowsAPI每日一练(2) 使用应用程序句柄

 

从上面这段程序就可以看到,_tWinMain是应用程序的入口函数,这里是使用它的宏,定义在tchar.h头文件里,为什么要这样作宏定义的呢?由于Windows的应用程序要适应UNICODE和以前单字符的应用程序,由于Windows这两个API的定义是不一样的,如下:
UNICODE的定义:
 #define _tWinMain   wWinMain
单字符的定义:
 #define _tWinMain   WinMain
只要经过这样的宏定义后,就可以适应不同字符宽度的函数接口了。由于我是采用UNICODE编译的,所以这里使用wWinMain函数定义,下面再把它的定义找出来,如下:
int
WINAPI
wWinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPWSTR lpCmdLine,
    int nShowCmd
);
这里要详细地解释一下函数wWinMain的参数,它有四个参数。
hInstance是当前应用程序的实例句柄,一般用来区分不同的资源使用。
hPrevInstance是以前Win98使用的句柄,在Win2000以后的操作系统里都是空值NULL。
lpCmdLine是命令行参数,比如你在Windows开始菜单里运行一个程序,并添加参数在后面,就会传递给应用程序,后面再详细讨论。
nShowCmd是窗口的显示方式,比如最大化显示,最小化显示,还是正常显示。
 
Windows运行程序时,是通过运行库里的启动代码来调用wWinMain函数,它是在启动文件里如下调用:
#ifdef WPRFLAG
            mainret = wWinMain(
#else /* WPRFLAG */
            mainret = WinMain(
#endif /* WPRFLAG */
                       (HINSTANCE)&__ImageBase,
                       NULL,
                       lpszCommandLine,
                       StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                        ? StartupInfo.wShowWindow
                        : SW_SHOWDEFAULT
                      );
这就是操作系统传递给应用程序的值,现在就来演示使用第一个参数hInstance。
请看下面的例子:
 1 #include<windows.h>
 2 
 3 int WINAPI wWinMain(
 4   HINSTANCE hInstance,      // handle to current instance
 5   HINSTANCE hPrevInstance,  // handle to previous instance
 6   LPSTR lpCmdLine,          // command line
 7   int nCmdShow              // show state
 8 )
 9 { 
10      UNREFERENCED_PARAMETER(hInstance);
11      UNREFERENCED_PARAMETER(hPrevInstance); 
12      UNREFERENCED_PARAMETER(lpCmdLine);
13      UNREFERENCED_PARAMETER(nCmdShow);    
14 
15      //使用应用程序句柄
16 
17      const int MAXSIZE_APPBUF = 256;
18      TCHAR wAppTitle[MAXSIZE_APPBUF];
19      LoadString(hInstance,IDS_APP_TITLE,wAppTitle,MAXSIZE_APPBUF);
20 
21 
22 
23     //获得桌面句柄
24     HWND hWnd=GetDesktopWindow();
25 
26     //显示第一行信息
27 //    ::MessageBox(hWnd,"Hello Window","Hello Window",MB_YESNO);
28     MessageBox(hWnd,"Hello Windows",wAppTitle,MB_YESNO);
29     return 0;
30 }

这个例子是在前面的基础上修改的,主要添加了使用应用程序实例句柄。在第19行里定义了一个保存应用程序标题的缓冲区,然后在第20行里调用函数LoadString从应用程序的资源里加载字符串,它的第一个参数就使用到hInstance句柄。因此应用程序句柄是表示程序在资源上唯一的标识符。

 


 

LoadString问题:

 作用:从 资源 里加载字符串资源到CString对象里。

声明:

 
 函数LoadString声明如下:
1 WINUSERAPI int WINAPI LoadStringA(
2 
3 __in_opt HINSTANCE hInstance,
4 
5 __in UINT uID,
6 
7 __out_ecount(cchBufferMax) LPSTR lpBuffer,
8 
9 __in int nBufferMax);

 

参数1: hInstance是应用程序实例句柄。

 

参数2: uID是资源中的字符串编号。

 

参数3: lpBuffer是接收从资源里拷贝字符串出来的缓冲区。

 

参数4: nBufferMax是指明缓冲的大小。

 

参数:

hInstance [in]:
Handle to an instance of the module whose executable file contains the string resource. To get the handle to the application itself, use GetModuleHandle(NULL).
uID [in] :
Specifies the integer identifier of the string to be loaded.
lpBuffer [out]:
Pointer to the buffer to receive the string.
nBufferMax [in]:
Specifies the size of the buffer, in TCHARs. This refers to bytes for ANSI versions of the function or WCHARs for Unicode versions. The string is truncated and NULL terminated if it is longer than the number of characters specified.

 

返回值:

If the function succeeds, the return value is the number of TCHARs copied into the buffer, not including the terminating NULL character, or zero if the string resource does not exist. To get extended error information, call GetLastError.

 

说明

Security Alert
Using this function incorrectly can compromise the security of your application. Incorrect use includes specifying the wrong size in the nBufferMax parameter. For example, if lpBuffer points to a buffer szBuffer which is declared as TCHAR szBuffer[100], then sizeof(szBuffer) gives the size of the buffer in bytes, which could lead to a buffer overflow for the Unicode version of the function. Buffer overflow situations are the cause of many security problems in applications. In this case, using sizeof(szBuffer)/sizeof(TCHAR) or sizeof(szBuffer)/sizeof(szBuffer[0]) would give the proper size of the buffer.

 

Windows 95/98/Me: LoadStringW is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows 95/98/Me Systems.

 

系统要求

 

Minimum DLL Version: user32.dll

 

Header: Declared in Winuser.h, include Windows.h

 

Import library: User32.lib

 

Minimum operating systems: Windows 95, Windows NT 3.1

 

Unicode: Implemented as ANSI and Unicode versions.

 

看完上面的资料可能大家都蒙了,不知道具体是在做什么,

 

其实这个成员函数是在调用String Table里面定义的信息,

 

也就是说,把String Table中Caption里面的字符串读出来到CString对象里。

 

String Table中的ID号及其对应的字符串都是可以自己定义的。

 

String Table在ResourceView窗口中,也就是ClassView右边那个窗口。

 

双击之后就能看到,在最下面的选项中追加新的ID信息。

 

如果还是理解不清楚的话,请自己尝试多读msdn里的英文及例子就明白了。

 

int LoadString(HINSTANCE hInstance,//应用程序实例句柄
UINT uID,//资源ID
LPTSTR lpBuffer,//存放字符串的缓冲区
int nBufferMax//缓冲区大小

作用:
先在资源中加入字符串资源(不管是字符串还是窗口还是按钮),都有一个名字,比如IDC_BUTTON1
然后用这个函数把这个名字作为参数,就可以取出资源中的字符串了

如:一、在resource.h中,#define FIREWALL_ALREADY_START           61452
二、在*.rc文件中:
STRINGTABLE DISCARDABLE
BEGIN
        FIREWALL_ALREADY_START “防火墙已经启动”
END

三、
CString str;
    str.LoadString(FIREWALL_ALREADY_START);