书上有时候用wndclass方式创建.
有时侯用SetWindowLong()GWL_WNDPROC的方式创建.两者有区别么?

解决方案 »

  1.   

    SetWindowLong()适合于改写别的公有类比如按钮什么的wndproc,
    而wndclass方式主要是在程序创建初期就定下来了。
      

  2.   

    以下是我仿效书上写的一个程序.
    用子窗口控制Scrollbar,但是,滑块会弹回的.我尝试不用子窗口,到是可以的.问题出在哪里啊?我想"子窗口"过程里的hwnd就是每个Scrollbar的句柄
    #include <windows.h>
    #include "resource.h"const int ID_REDSCROLL=0;
    const int ID_BLUESCROLL=1;
    const int ID_GREENSCROLL=2;const int ID_REDBUTTON=3;
    const int ID_BLUEBUTTON=4;
    const int ID_GREENBUTTON=5;const int ID_TABLE=6;int       idFocus;
    int   scrollPos[3];
    WNDPROC   scrollProc[3];LRESULT CALLBACK WndProc (HWND, UINT, WPARAM , LPARAM );
    LRESULT CALLBACK ScrollProc (HWND, UINT , WPARAM , LPARAM );
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName[] = TEXT ("ColorTable") ;
         HWND         hwnd ;
         MSG          msg ;
         WNDCLASS     wndclass ;
         
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = WndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = sizeof(long);
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (hInstance,TEXT ("ColorTable")) ;
         wndclass.hCursor       = LoadCursor (0,IDC_CROSS) ;
         wndclass.hbrBackground = (HBRUSH) (GetStockObject(BLACK_BRUSH)) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szAppName ;
         
         if (!RegisterClass (&wndclass)){
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                          szAppName, MB_ICONERROR) ;
              return 0 ;
         }
         
         hwnd = CreateWindow (szAppName, TEXT ("ColorTable"),
                              WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                              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 HBRUSH      hBrush[3];    
      static bool  notFrozen[3];
      static HWND  tableHwnd,scrollHwnd[3],colorLableHwnd[3];
      static int         cxClient,cyClient,cxChar,cyChar;   int  i,id;
      COLORREF           color[3]={RGB(225,0,0),
       RGB(0,0,225),
       RGB(0,225,0)
    };   switch(message){
        case WM_CREATE:
     tableHwnd=CreateWindow(TEXT("static"),0,
        WS_CHILD|WS_VISIBLE|SS_WHITERECT,
        0,0,0,0,
        hwnd,(HMENU)ID_TABLE,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),0);
     SetClassLong(tableHwnd,GCL_HCURSOR,
    (long)LoadCursor((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
    MAKEINTRESOURCE(IDC_POINTER)));      for(i=0; i<3; i++){
       scrollHwnd[i]=CreateWindow(TEXT("scrollbar"),0,
      WS_CHILD|WS_VISIBLE|WS_TABSTOP|SBS_HORZ,
      0,0,0,0,
      hwnd,(HMENU)i,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),0);    
       SetScrollRange(scrollHwnd[i],SB_CTL,0,225,true);
       SetScrollPos(scrollHwnd[i],SB_CTL,0,true);
       scrollProc[i]=(WNDPROC)SetWindowLong(scrollHwnd[i],GWL_WNDPROC,(long)ScrollProc);    hBrush[i]=CreateSolidBrush(color[i]);
       notFrozen[i]=true;    colorLableHwnd[i]=CreateWindow(TEXT("button"),0,
      WS_CHILD|WS_VISIBLE|WS_BORDER|BS_OWNERDRAW,
      0,0,0,0,
      hwnd,(HMENU)(i+3),(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),0);
     }      return 0; case WM_CTLCOLORSCROLLBAR:
     i=GetDlgCtrlID((HWND)lParam);
     return (LRESULT)hBrush[i]; case WM_DRAWITEM:
     RECT rc;
     LPDRAWITEMSTRUCT pdis;
     int cx,cy;

     pdis=(LPDRAWITEMSTRUCT)lParam;
     cx=pdis->rcItem.right-pdis->rcItem.left;
     cy=pdis->rcItem.bottom-pdis->rcItem.top;      FrameRect(pdis->hDC,&pdis->rcItem,(HBRUSH)GetStockObject(BLACK_BRUSH));    switch(pdis->CtlID){
    case ID_REDBUTTON:
     FillRect(pdis->hDC,&pdis->rcItem,CreateSolidBrush(RGB(225,0,0)));
     break; case ID_BLUEBUTTON:
     FillRect(pdis->hDC,&pdis->rcItem,CreateSolidBrush(RGB(0,0,225)));
     break; case ID_GREENBUTTON:
     FillRect(pdis->hDC,&pdis->rcItem,CreateSolidBrush(RGB(0,225,0)));
     break;
     }

     if(pdis->itemState & ODS_SELECTED)
      InvertRect(pdis->hDC,&pdis->rcItem);
     
     if(pdis->itemState & ODS_FOCUS){
      rc.left  =pdis->rcItem.left  + cx/16;
      rc.right =pdis->rcItem.right - cx/16;
      rc.top   =pdis->rcItem.top   + cy/12;
      rc.bottom=pdis->rcItem.bottom- cy/12;   DrawFocusRect(pdis->hDC,&rc);
     }  return 0;     case WM_SIZE:
     cxChar=LOWORD(GetDialogBaseUnits());
     cyChar=HIWORD(GetDialogBaseUnits());
         cxClient=LOWORD(lParam);
     cyClient=HIWORD(lParam);  MoveWindow(tableHwnd,0,cyClient/2,cxClient,cyClient/2,true);
     
     for(i=0; i<3; i++){
     MoveWindow(scrollHwnd[i],cxClient/8,(i+3)*cyClient/6+cyChar,
                          7*cxClient/8-cxChar,cyChar,true);
     MoveWindow(colorLableHwnd[i],cxChar,(i+3)*cyClient/6+cyChar,
                              cxClient/10,cyChar,true);
     }
     
     SetFocus(scrollHwnd[idFocus]);
     return 0;
    case WM_COMMAND:
     switch(LOWORD(wParam)){
    case ID_REDBUTTON:
     EnableWindow(scrollHwnd[ID_REDSCROLL],notFrozen[ID_REDSCROLL]^=true);
     break; case ID_BLUEBUTTON:
     EnableWindow(scrollHwnd[ID_BLUESCROLL],notFrozen[ID_BLUESCROLL]^=true);
     break; case ID_GREENBUTTON:
     EnableWindow(scrollHwnd[ID_GREENSCROLL],notFrozen[ID_GREENSCROLL]^=true);
     break;
     }  return 0; case WM_MOUSEMOVE:
     int mx,my;
     mx=LOWORD(lParam);
     my=HIWORD(lParam);  if((mx>0 && mx<cxClient) && (my>0 && my<cyClient/2)){
     DeleteObject((HBRUSH)SetClassLong(hwnd,GCL_HBRBACKGROUND,
    (long)CreateSolidBrush(RGB(scrollPos[ID_REDSCROLL]+mx%256,
       scrollPos[ID_BLUESCROLL]+my%256,
       scrollPos[ID_GREENSCROLL]+(mx+my)%256))));
    InvalidateRect(hwnd,0,true);
     }

     return 0; case WM_DESTROY:
     for(i=0; i<3; i++)
    DeleteObject(hBrush[i]);  DeleteObject((HBRUSH)
    SetClassLong(hwnd,GCL_HBRBACKGROUND,
    (long)GetStockObject(WHITE_BRUSH)));             PostQuitMessage(0);
                 return 0;
      }
          return DefWindowProc(hwnd, message, wParam, lParam);
    }LRESULT CALLBACK ScrollProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
    int   ctrlID=GetDlgCtrlID(hwnd); switch(message){
    case WM_HSCROLL:
     switch(LOWORD(wParam)){
    case SB_PAGERIGHT:
     scrollPos[ctrlID]+=15;
    case SB_LINERIGHT:
     scrollPos[ctrlID]=min(225,scrollPos[ctrlID]+1);
     break;

    case SB_PAGELEFT:
     scrollPos[ctrlID]-=15;
    case SB_LINELEFT:
     scrollPos[ctrlID]=max(0,scrollPos[ctrlID]-1);
     break; case SB_THUMBPOSITION:
    case SB_THUMBTRACK:
     scrollPos[ctrlID]=HIWORD(wParam);
     break;
     }

     SetScrollPos(hwnd,SB_CTL,scrollPos[ctrlID],true);  DeleteObject((HBRUSH)
    SetClassLong(GetParent(hwnd),GCL_HBRBACKGROUND,
    (long)CreateSolidBrush(RGB(scrollPos[ID_REDSCROLL],
       scrollPos[ID_BLUESCROLL],
       scrollPos[ID_GREENSCROLL]))));
     InvalidateRect(GetParent(hwnd),0,true);  
     return 0;
     
       case WM_KEYDOWN:
        switch(wParam){
    case VK_TAB:
     SetFocus(GetDlgItem(GetParent(hwnd),(ctrlID+1)%3));
         idFocus=(ctrlID+1)%3;
     break;
    }
    return 0;
    } return CallWindowProc(scrollProc[ctrlID],hwnd,message,wParam,lParam);
    }
      

  3.   

    请问一下怎么动态改变CEdit控件颜色,是不是需要子类化窗口。
      

  4.   

    好象是需要反射机制,ON_WM_CTLCOLOR_REFLECT
      

  5.   

    to allen1981813(初级菜鸟) :
    在ScrollProc函数中接收不了WM_HSCROLL消息,我也觉得奇怪。可能这条消息是由父窗口处理吧?
    我在你的程序的WndProc函数中加了条语句,由父窗口传递一条消息。
    case WM_HSCROLL:
         SendMessage((HWND) lParam,WM_HSCROLL,wParam,lParam);
         return 0;
    就可以了。现在我的问题是:到底子控制可以接收哪些消息。
      

  6.   

    诶,
    哥们你是如何想到的.我个人认为,没有道理呀?我当时设计主窗口过程的时候没有加入任何滚动条风格呀?应该不会有主窗口的WM_HSCROLL.想不通?
      

  7.   

    窗口子类化只有SetWindowLong()一种方式,哪来另一种方式。
    窗口子类化的前提是目标窗口已经创建!
      

  8.   

    to allen1981813(初级菜鸟) :
          我明白了,WM_HSCROLL是由卷滚条向父窗口发送的一条消息,所以自己不能直接接收了。mfc中的反射就是用的这个原理,将发往父窗口的消息再由父窗口反射回来,就可以解决了。
      

  9.   

    superzrb(cafe) 
    我更加糊了.
    在"子过程"中
    hwnd是scrollbar,如何是父窗口?
      

  10.   

    scrollbar是公有类,所以可以窗口子类化,但我问非公有类是否可以子类化?           发出WM_HSCROLL消息
    scrollbar----------------------->父窗口
             <-----------------------
               反馈回去WM_HSCROLL消息WM_HSCROLL是由scrollbar向外发出的,你的最初的程序一开始就在scrollbar中接收,殊不知WM_HSCROLL是由scrollbar向外发出的。
      

  11.   

    那,
    windows编程中是不是大多是按照这种发送与反馈的机制呢?
      

  12.   

    反馈回去WM_HSCROLL消息是我自己写的啊。就是那段加的代码呀。反馈应该都是自己写的吧。我不是高手啊。呵呵。共同讨论。