#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 的作用?

解决方案 »

  1.   

    1.是注册了两个窗口类.你没看懂代码.调用了两次RegisterClass.一次注册主窗口,一次注册子窗口.成员的值有修改的.
    2.不清楚就看看MSDN.
    3.WM_CREATE在这个窗口创建的时候调用的.不是不行.而是你怎么放的.出什么错了??贴出来啊.
    4.仔细看一下WNDCLASS结构体的相关说明.
    5.6.多看MSDN......
      

  2.   

    2.cbClsExtra 
    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上都说的很清楚啊
      

  3.   

    1,确实是注册了两个窗口类,不过它用了同一个wndclass变量
    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. 
      

  4.   

    感谢上面两位
    MSDN里面大多是英文的,而且有些专业术语我不是很理解,所以导致整个功能都不理解,所以我也不太爱查MSDN。
    回复一楼的:
        我把那段代码连同其中用到的那些变量一起放到WinMain中,编译成功,运行后窗口中却没有显示出那些格子。
      

  5.   

    回楼上几位
        第一个RegiterClass后面紧跟着就修改了WndClass中的值然后第二次注册,那紧接其后的CreateWindow所创造的窗口不应该是第二次注册的值吗?为什么会还是第一次的赋值?
    那我想问这里的cbClsExtra是什么用?他赋了一个sizeof(long)。那段WM_CREATE后的代码我放到了UpdateWindow之后
      

  6.   

    第一个RegiterClass后面紧跟着就修改了WndClass中的值然后第二次注册,那紧接其后的CreateWindow所创造的窗口不应该是第二次注册的值吗?为什么会还是第一次的赋值? 
    ================================
    CreateWindow到底到哪个窗口类要看参数,CreateWindow中的第一个参数是类名,这个类名和窗口类中的类一样才行。我把那段代码连同其中用到的那些变量一起放到WinMain中,编译成功,运行后窗口中却没有显示出那些格子。
    =========================================
    你对Windows的消息驱动方式好像没有理解啊,你在WinMain放入一段代码,在WM_CREATE消息来时,它怎么调用啊。
      

  7.   

    回复六楼:
        Register最后产生了一个以WNDCLASS填写的类名为名字的类?如果是这样我就可以理解后面为什么值被变了产生的结果却不变。
    主窗口的窗口显示的代码不也是放在WinMain中吗?子窗口为什么不行呢?
    还有为什么主窗口显示要一个showwindow,而子窗口不需要呢?直接createwindow就可以了……WHY?