最早時候就曾經哪里看到過說所有控件都是窗口(window),更有甚者說都是對象,這個就不扯了。自己做好的控件是做成Lib還是Dll那是后話,MFC我是不熟悉了,Win32還是看了幾天的。大致把制作的整個流程簡要的記錄一下。

自己做的控件最主要的功能就是接受你發給他的命令,也就是要給外部調用的接口。控件有自己的消息處理函數比如

LRESULT CALLBACK PETextViewWndProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
    PETextView 
*View = (PETextView*)GetWindowLong(hWnd,0);

    
switch(Message)
    
{
    
case WM_NCCREATE:
        
if((View = new PETextView(hWnd)) == 0)
            
return false;

        SetWindowLong(hWnd,
0,(LONG)View);
        
return true;

    
case WM_NCDESTROY:
        
if(View)delete View;
        
return 0;

    
case WM_PAINT:
        
return View->OnPaint();

    
case WM_SIZE:
        
return View->OnSize(wParam, LOWORD(lParam), HIWORD(lParam));

    
case PEM_OPENFILE:
        
return View->OpenFile((TCHAR*)lParam);

    
case PEM_CLEAR:
        
return View->ClearFile();
    
default:
        
break;
    }


    
return DefWindowProc(hWnd,Message,wParam,lParam);
}


這里有兩類消息,一類是系統定義的以WM開頭,一類是自己定義的,當然隨便你自己定義啦。對應的消息看到是調用相應的函數完成的,這也就是說控件的行為就可以另外編寫邏輯部分,然后提供接口給這里調用即可。

之所以說控件就是窗口是因為他有自己的窗口類,以及初始化函數,同時也有創建的函數。窗口類的定義和注冊也做成提供給外部的接口,在外部必要的時候調用。而控制控件是通過發送消息來實現的,為了更加好看,可以定義一個宏,比如

#define PE_OpenFile(hWnd, Path)        SendMessage((hWnd), PEM_OPENFILE, 0, (LPARAM)(Path))

那么創建窗口和控件唯一不同的地方就是,內部的創建和銷毀消息是WM_NCCREATEWM_NCDESTROY,先不管這兩個消息。我們看到WM_NCCREATE之前有個GetWindowLong,其內有個SetWindowLong。這兩個是關鍵的,這樣就設置了這個控件的屬性,使其關聯起來,第二個參數msdn上是沒有說明設置為0是什么意思的,其實這兩個函數的第二個參數設置0表示讀取的意思,第一個是讀取該控件的屬性,然后第二個函數在增加第三個參數的屬性的同時讀取賦予給這個控件。

 

一切都OK了!那么控件創建可在外部的WM_CREATE之時調用,當然也可以在使用其功能前調用即可。

 

一切提供給外部的調用都Port在一個頭文件中,這樣使用的時候包含這個頭文件就好了。

接下來解釋那兩個消息,這兩個消息是因為我們創建了子窗口,也就是我們自己的控件。

這兩個消息與WM_CREATE,WM_DESTROY之間的順序關系是這樣的,只看銷毀吧。

hwnd = parent, uMsg = WM_DESTROY
hwnd = child, uMsg = WM_DESTROY
hwnd = child, uMsg = WM_NCDESTROY
hwnd = parent, uMsg = WM_NCDESTROY

WM_DESTROY是通知子窗口銷毀,然后子窗口通過接受WM_NCDESTROY進行銷毀,并發送給父窗口,進行銷毀。

 

細節部分介紹的差不多,總體思路就是和創建窗口差不多,但是要搞個頭文件,把一些個常量和功能的函數另外一個窗口類的初始化和創建的接口搞進去。