#include <windows.h>
#define DIVISIONS 5
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szChildClass[] = TEXT ("Checker3_Child") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Checker3") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox ( NULL, TEXT ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
wndclass.lpfnWndProc = ChildWndProc ;
wndclass.cbWndExtra = sizeof (long) ;
wndclass.hIcon = NULL ;
wndclass.lpszClassName = szChildClass ;
RegisterClass (&wndclass) ;
hwnd = CreateWindow (szAppName, TEXT ("Checker3 Mouse Hit-Test Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
static HWND hwndChild[DIVISIONS][DIVISIONS] ;
int cxBlock,cyBlock,x,y;
switch (message)
{
case WM_CREATE :
for (x = 0 ; x < DIVISIONS ; x++)
for (y = 0 ; y < DIVISIONS ; y++)
hwndChild[x][y] = CreateWindow(szChildClass, NULL,
WS_CHILDWINDOW | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU) (y << 8 | x),
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
return 0 ;
case WM_SIZE :
cxBlock = LOWORD (lParam) / DIVISIONS ;
cyBlock = HIWORD (lParam) / DIVISIONS ;
for (x = 0 ; x < DIVISIONS ; x++)
for (y = 0 ; y < DIVISIONS ; y++)
MoveWindow ( hwndChild[x][y],
x * cxBlock, y * cyBlock,
cxBlock, cyBlock, TRUE) ;
return 0 ;
case WM_LBUTTONDOWN :
MessageBeep (0) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE :
SetWindowLong (hwnd, 0, 0) ; // on/off flag
return 0 ;
case WM_LBUTTONDOWN :
SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ;
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;
if (GetWindowLong (hwnd, 0))
{
MoveToEx (hdc, 0, 0, NULL) ;
LineTo (hdc, rect.right, rect.bottom) ;
MoveToEx (hdc, 0, rect.bottom, NULL) ;
LineTo (hdc, rect.right, 0) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
上面的代码中我有一些疑问。。
1.WinMain函数中不用定义两个WNDCLASS吗?其中一个不是给主窗口用的吗,子窗口也用同一个WNDCLASS,主窗口怎么办?
2.WinMain函数中的wndclass.cbWndExtra = sizeof (long) ;这句我不懂,本身我就不清楚cbWndExtra和cbClsExtra 的用处了。
3.WndProc回调函数中的WM_CREATE消息响应部分的那段代码我放在WinMain中,却不行?为什么?
还有这段代码用了CreateWindow把子窗口放入了内存中,不用一个ShowWindow显示出来吗?
4.还是上面那段代码中的(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),说是获得子窗口的实例句柄,能详细解释一下吗?
5.ChildWndProc回调函数中的SetWindowLong (hwnd, 0, 0) ;这句的作用?
6.GetWindowLong 的作用?
#define DIVISIONS 5
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szChildClass[] = TEXT ("Checker3_Child") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Checker3") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox ( NULL, TEXT ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
wndclass.lpfnWndProc = ChildWndProc ;
wndclass.cbWndExtra = sizeof (long) ;
wndclass.hIcon = NULL ;
wndclass.lpszClassName = szChildClass ;
RegisterClass (&wndclass) ;
hwnd = CreateWindow (szAppName, TEXT ("Checker3 Mouse Hit-Test Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
static HWND hwndChild[DIVISIONS][DIVISIONS] ;
int cxBlock,cyBlock,x,y;
switch (message)
{
case WM_CREATE :
for (x = 0 ; x < DIVISIONS ; x++)
for (y = 0 ; y < DIVISIONS ; y++)
hwndChild[x][y] = CreateWindow(szChildClass, NULL,
WS_CHILDWINDOW | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU) (y << 8 | x),
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
return 0 ;
case WM_SIZE :
cxBlock = LOWORD (lParam) / DIVISIONS ;
cyBlock = HIWORD (lParam) / DIVISIONS ;
for (x = 0 ; x < DIVISIONS ; x++)
for (y = 0 ; y < DIVISIONS ; y++)
MoveWindow ( hwndChild[x][y],
x * cxBlock, y * cyBlock,
cxBlock, cyBlock, TRUE) ;
return 0 ;
case WM_LBUTTONDOWN :
MessageBeep (0) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE :
SetWindowLong (hwnd, 0, 0) ; // on/off flag
return 0 ;
case WM_LBUTTONDOWN :
SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ;
InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;
if (GetWindowLong (hwnd, 0))
{
MoveToEx (hdc, 0, 0, NULL) ;
LineTo (hdc, rect.right, rect.bottom) ;
MoveToEx (hdc, 0, rect.bottom, NULL) ;
LineTo (hdc, rect.right, 0) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
上面的代码中我有一些疑问。。
1.WinMain函数中不用定义两个WNDCLASS吗?其中一个不是给主窗口用的吗,子窗口也用同一个WNDCLASS,主窗口怎么办?
2.WinMain函数中的wndclass.cbWndExtra = sizeof (long) ;这句我不懂,本身我就不清楚cbWndExtra和cbClsExtra 的用处了。
3.WndProc回调函数中的WM_CREATE消息响应部分的那段代码我放在WinMain中,却不行?为什么?
还有这段代码用了CreateWindow把子窗口放入了内存中,不用一个ShowWindow显示出来吗?
4.还是上面那段代码中的(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),说是获得子窗口的实例句柄,能详细解释一下吗?
5.ChildWndProc回调函数中的SetWindowLong (hwnd, 0, 0) ;这句的作用?
6.GetWindowLong 的作用?
2.不清楚就看看MSDN.
3.WM_CREATE在这个窗口创建的时候调用的.不是不行.而是你怎么放的.出什么错了??贴出来啊.
4.仔细看一下WNDCLASS结构体的相关说明.
5.6.多看MSDN......
Specifies the number of extra bytes to allocate following the window-class structure. The system initializes the bytes to zero.
4.SetWindowLong 设置窗口风格,GetWindowLong 当然就是得到啦
LONG SetWindowLong(
HWND hWnd, // handle to window
int nIndex, // offset of value to set
LONG dwNewLong // new value
);
这些msdn上都说的很清楚啊
2,cbWndExtra和cbClsExtra 前者是指将一个数据放到一个与窗口相关联的一个内存区域中去,后者是与窗口类相关联的一个内存区域,
3,这个问题我看不懂,消息的处理程序你怎么可能放到WinMain中去呢,怎么放的呢?
至于GetWindowLong和SetWindowLong这两个API能得到或设置一些窗口的属性,比如窗口的风格,等,具体的看MSDN:
GetWindowLong
The GetWindowLong function retrieves information about the specified window. The function also retrieves the 32-bit (long) value at the specified offset into the extra window memory. If you are retrieving a pointer or a handle, this function has been superseded by the GetWindowLongPtr function. (Pointers and handles are 32 bits on 32-bit Windows and 64 bits on 64-bit Windows.) To write code that is compatible with both 32-bit and 64-bit versions of Windows, use GetWindowLongPtr. LONG GetWindowLong(
HWND hWnd, // handle to window
int nIndex // offset of value to retrieve
);
Parameters
hWnd
[in] Handle to the window and, indirectly, the class to which the window belongs.
nIndex
[in] Specifies the zero-based offset to the value to be retrieved. Valid values are in the range zero through the number of bytes of extra window memory, minus four; for example, if you specified 12 or more bytes of extra memory, a value of 8 would be an index to the third 32-bit integer. To retrieve any other value, specify one of the following values. Value Action
GWL_EXSTYLE Retrieves the extended window styles. For more information, see CreateWindowEx.
GWL_STYLE Retrieves the window styles.
GWL_WNDPROC Retrieves the address of the window procedure, or a handle representing the address of the window procedure. You must use the CallWindowProc function to call the window procedure.
GWL_HINSTANCE Retrieves a handle to the application instance.
GWL_HWNDPARENT Retrieves a handle to the parent window, if any.
GWL_ID Retrieves the identifier of the window.
GWL_USERDATA Retrieves the user data associated with the window. This data is intended for use by the application that created the window. Its value is initially zero.
MSDN里面大多是英文的,而且有些专业术语我不是很理解,所以导致整个功能都不理解,所以我也不太爱查MSDN。
回复一楼的:
我把那段代码连同其中用到的那些变量一起放到WinMain中,编译成功,运行后窗口中却没有显示出那些格子。
第一个RegiterClass后面紧跟着就修改了WndClass中的值然后第二次注册,那紧接其后的CreateWindow所创造的窗口不应该是第二次注册的值吗?为什么会还是第一次的赋值?
那我想问这里的cbClsExtra是什么用?他赋了一个sizeof(long)。那段WM_CREATE后的代码我放到了UpdateWindow之后
================================
CreateWindow到底到哪个窗口类要看参数,CreateWindow中的第一个参数是类名,这个类名和窗口类中的类一样才行。我把那段代码连同其中用到的那些变量一起放到WinMain中,编译成功,运行后窗口中却没有显示出那些格子。
=========================================
你对Windows的消息驱动方式好像没有理解啊,你在WinMain放入一段代码,在WM_CREATE消息来时,它怎么调用啊。
Register最后产生了一个以WNDCLASS填写的类名为名字的类?如果是这样我就可以理解后面为什么值被变了产生的结果却不变。
主窗口的窗口显示的代码不也是放在WinMain中吗?子窗口为什么不行呢?
还有为什么主窗口显示要一个showwindow,而子窗口不需要呢?直接createwindow就可以了……WHY?