最早時候就曾經哪裡看到過說所有控制項都是視窗(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_NCCREATE和WM_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進行銷毀,並發送給父視窗,進行銷毀。
細節部分介紹的差不多,總體思路就是和建立視窗差不多,但是要搞個標頭檔,把一些個常量和功能的函數另外一個視窗類別的初始化和建立的介面搞進去。