程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 接觸VC之一:WinSDK

接觸VC之一:WinSDK

編輯:關於VC++

預設目錄:

第一部分:WinSDK

第二部分:MFC類基礎,C++程序編寫規范介紹

第三部分:MFC基於對話框程序

第四部分:Dll動態鏈接庫

第五部分:COM組件基礎

第六部分:COM組件幾個常用技術:IDispatch,可連接對象.

第七部分:COM組件的應用,以及MFC的COM編寫

第一部分:WinSDK

學習VC已近一年了,回顧我的學習歷史真是相當的艱苦。既沒有老師教,圖書館裡也沒有好書可看。為了買到好書,身上的銀子幾近花光,不得不過節衣縮食的生活。近些日來動起自己寫寫什麼的打算,一來可以對自己的學習狀況進行總結。二來,請教高手,可以幫忙指出錯漏之處。三來,說不定會對初學者們有所幫助, 最起碼也可以練練文筆。

OK。談正事喽。首先MFC(Microsoft Foundation Class)是一種用來構建Win32程序的類庫,但究其根本的話,是基於Windows老祖宗—Windows SDK,其歷史可以追溯到Window 3.x時代。它整個構架是由C來編寫的。更重要的是它的程序結構至今還是Win32程序的根本。因此,在學習VC的過程中,理解其程序結構是編寫Win32程序的根本。

下面,就是一個WinSDK程序的示例(摘自侯先生的《深入淺出MFC》,在侯捷站點上有其此書的繁體電子版)

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
  MSG msg;
  if (!hPrevInstance)
  if (!InitApplication(hInstance))
    return (FALSE)
  if (!InitInstance(hInstance, nCmdShow))
    return (FALSE);
  while (GetMessage(&msg, NULL, 0, 0))
  {
    TranslateMessage(&msg);
    DispatchMessage (&msg);
  }
  return (msg.wParam);
}
BOOL InitApplication(HINSTANCE hInstance)
{
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = (WNDPROC)WndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon(hInstance, "jjhouricon");
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  wc.lpszMenuName = "GenericMenu";
  wc.lpszClassName = "MyWindow";
  return (RegisterClass(&wc));
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
  hWnd = CreateWindow("MyWindow","This is Windows SDK",
  WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  NULL,
  NULL,
  hInstance,
  NULL);
  if (hWnd == NULL)
    return (FALSE);
  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);
  return (TRUE);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message)
  {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowPro(hWnd, message, wParam, lParam);
}
  return 0;
}

首先,在C語言中的入口函數是main函數,在Win32程序中則是WinMain。其原型是

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int CmdShow)

第一個參數是hInstance,是所傳進來的值是此程序的當前程序實例句柄。什麼叫實例呢?當你運行兩次同一個Windows程序時,屏幕上會出現兩個一模一樣的窗口;這時我們就說這個程序就被生成了兩個實例。再舉一個例子,在你眼前擱仨蘋果,其時這個仨蘋果就是蘋果這一大類的三個實例。按照這個思路說實例就是一個抽象概念中的實體存在。那麼嚴格來說其時我們所編寫的並不是這個程序,而是這個程序的邏輯。而程序實例則是按照這個我們編寫的邏輯所生成的實體結果。而句柄就是用來代表實例的,它是一個32位的值。每一個實例都對就著一個32位的值,而這個值就被稱為句柄。不知道我說明白沒有。這裡的Instance就是當前程序被實例化後的句柄。而且屬於同一個實例中的資源是共享的。第二個參數hPreInstance則代表上一個(前一個)程序實例句柄,在Win32程序中這個值總為空(為零),第三個參數是lpCmdLine,這是一個字符串,記錄著啟動程序時的命令行,起著C中main函數的(argc,argv)的作用.最後nCmdShow則表示這個程序的窗口是否被顯示出來。

在主函數中,第一個要執行的函數就是InitApplication(),語句如下:

if (!InitApplication(hInstance))
return (FALSE);

這個函數所起的作用是注冊窗口類。注冊窗口類的意思就是告訴系統將我們的提供的圖標,菜單,消息處理函數,光標聯系起來成為一個窗口類,為後面的顯示窗口作准備。在InitApplication()函數中使用RegisterClass()來注冊窗口。如果成功則返回true,否則返回false。其唯一的參數是一個WNDCLASS結構。其中各字段功能如下:(關於具體值請查看MSDN)

style 指定窗口風格,譬如例子所舉的CS_HREDRAW表示當水平長度發生改變時,重畫整個窗口。 LpfnWndProc 指定窗口的消息處理函數,其函數的原型必須是

LRESULT CALLBACK WndProcName(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

WndProcName這一名字是隨便起的.

hInstance 標識該窗口屬於哪個程序實例.

hIcon 標識該窗口圖標的圖標句柄

hCurosr 標識該窗口光標的光標句柄

hbrBackground 標識該窗口的背景畫筆.

lpszClassName 為這個窗口類所起的名字,為後來建立窗口引用窗口類所用。

當注冊窗口類成功後就可以建立窗口了。主函數調用InitInstance()來建立窗口.在InitInstance()函數中使用CreateWindow();來建立窗口,其中第一個參數就是窗口類的名稱,則注冊窗口類時lpszClassName字段中的內容。如果成功則返回句柄,句柄代表剛剛建立好的窗口(實例)。否則的話返回的句柄為空。當建立好窗口的並不立即顯示,還需用ShowWindow來使系統顯示窗口,其參數就是一個窗口句柄(HWND)。看吧,在WinSDK中都是句柄來標識任何東西的(程序,窗口,圖標,光標,文件等等)。然後再使用UpdateWindow()讓窗口在屏幕上重繪一遍,使其真正顯示出來。最後返回true.

接著就是WinSDK中重要一節消息循環:

while (GetMessage(&msg, NULL, 0, 0))
{
  TranslateMessage(&msg);
  DispatchMessage (&msg);
}

在每個程序實例中系統都會給配置了一個消息隊列,當消息產生後(譬如:刷新WM_PAINT,鼠標移動WM_MOSEMVOE,鍵盤某個鍵被按下WM_KEYDOWN等等),就會將其放入隊列尾部。程序這裡用了一個while循環,這就是著名的消息循環了。GetMessage()在隊列頭部取出一條消息放入第一參數msg中,如果不是WM_QUIT (退出程序消息)消息則返回true,如果是WM_QUIT則返回false,結束循環。循環中第一個函數TranslateMessage()是鍵盤轉換函數,其功能是將虛擬鍵消息轉換成字符消息:

*WM_KEYDOWN/WM_KEYUP組合成一個WM_CHAR或WM_DEADCHAR消息

*WM_SYSKEYDOWN/WM_SYSKEYUP組合成一個WM_SYSCHAR或WM_SYSDEADCHAR消息。

並將組合成的消息放到隊列當中去,等以後處理。

DispatchMessage()函數是將消息傳送給相應的窗口消息處理函數中去。在MSG結構中有一個HWND字段它記錄著產生消息的窗口,DispatchMessage會查找這個HWND句柄屬於哪個窗口類,並將消息傳入這個窗口類所聯系的消息處理函數(在WNDCLASS結構中LpfnWndProc字段所指向的函數)中去。這樣它就完成了它的消息分配工作。在上面示例程序中,只注冊了一個窗口類。所以所有消息都是由這個窗口類的窗口實例所產生的,因此所有的消息都會被傳入WinProc中去了。

在消息處理函數的入口參數中,是標識一條消息的主要信息,hWnd發生消息的源窗口,message消息的類型表示發生了什麼消息,wParam,lParam與消息捆綁來的信息。因為在C\C++中類型是可以自由轉換的,所以根據不同消息,其裡面的內容是不一致。在消息處理函數中一般上是用switch/case語句來實現不同消息不同處理的。相信大家一看就明白怎麼回事了。

關於message中的信息在VC98\Include\WinUSER.h(參考行數1292)中有詳細的定義,各個消息的涵義可在MSDN中查到。

以上,就是我所知道的WinSDK所有東西。如果有什麼錯誤和遺漏之處,請寫信給我:[email protected];QQ:63068279。

(第一部分完)

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved