众所周知,在windows下我们要创建窗口,必须依据一个已经有的或者自己创建一个新的窗口类,然后注册窗口类,最后才能根据这个窗口类创建一个用户自己的窗口,MSDN中WNDCLASS的类型定义为
typedef struct _WNDCLASS {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;
注意这里已经有了HINSTANCE hInstance的定义,当我们定义了这样一个结构体后,根据这个结构体去注册这个窗口类,
调用ATOM RegisterClass( CONST WNDCLASS *lpWndClass // class data)即可,这样我们就可以根据这个窗口类创建窗口了
然而让人疑惑的是HWND CreateWindow(
LPCTSTR lpClassName, // registered class name
LPCTSTR lpWindowName, // window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // menu handle or child identifier
HINSTANCE hInstance, // handle to application instance
LPVOID lpParam // window-creation data
);中再次指定了hInstance,我们读windows编程或者其它常见的windows编程的书大体介绍都是CreateWindow是根据lpClassName这个变量创建新的窗口的,既然根据窗口类就可以创建窗口,而窗口类中已经有了关于hInstance的声明了,为什么还要重新声明,这不是多此一举吗?这下可把初学windows编程的很多人搞晕了,哈哈
尽信书不如无书,同学们想一想,当同一个程序的执行后,重新开启第二次执行的时候,两次注册的窗口类的名字是否一样呢?答案当然是肯定的,因为多个进程执行的代码段是相同的,但是每个进程的窗口类却不一样,因为在窗口类中还有一个hInstance的声明,用数据库的观点看就是说窗口类的主键不止是lpClassName而已,还有hInstance,这样以来当CreateWindow时当然同时需要指定窗口的lpClassName和hInstance喽
结论:窗口类名不足以唯一地标志窗口类。每个进程有自己的窗口类列表,窗口类列表中的每一项都由一个实例句柄和一个类名字组成。创建窗口时,windows的窗口管理器使用实例句柄和窗口类的组合来寻找窗口类。