青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品


姚明,81年,97年開始接觸電腦,6年的編程學(xué)習(xí)經(jīng)歷, 曾有4年工作經(jīng)驗(yàn),最終轉(zhuǎn)向基礎(chǔ)理論學(xué)習(xí)和研究, 現(xiàn)華中理工科技大學(xué)在讀,有志于圖形學(xué)領(lǐng)域工作發(fā)展

EMAIL:alanvincentmail@gmail.com QQ:31547735

隨筆分類(34)

文章分類(99)

相冊(cè)

收藏夾(6)

編程技術(shù)網(wǎng)站

出國(guó)留學(xué)網(wǎng)站

數(shù)學(xué)資源網(wǎng)站

圖形學(xué)網(wǎng)站

  • ati
  • ati開發(fā)者
  • azure
  • 葉蔚的個(gè)人網(wǎng)站
  • cnblogs
  • 計(jì)算機(jī)圖形學(xué)群
  • directx
  • directx官方網(wǎng)站
  • Eurographics
  • 計(jì)算機(jī)圖形學(xué)年會(huì)
  • gamedev
  • 游戲編程網(wǎng)站
  • nvidia
  • nvidia開發(fā)者
  • opengl
  • opengl官方網(wǎng)站
  • opengpu
  • GPU 相關(guān)的圖形學(xué)技術(shù)
  • SCI
  • 圖形學(xué)論文
  • siggraph
  • 世界圖形學(xué)年會(huì)
  • Tim Rowley
  • 收集整理了頂級(jí)年會(huì)的論文合集

英語(yǔ)資源網(wǎng)站

自由職業(yè)者

搜索

  •  

最新評(píng)論

 

跟我一起學(xué)圖形編程

                              作者:姚明           聯(lián)系方式:alanvincentmail@gmail.com     2011年1月22日 18:46:14

歡迎使用我的圖形學(xué)教程。我是計(jì)算機(jī)專業(yè)的學(xué)生,對(duì)圖形圖像技術(shù)有濃厚的興趣,就讀期間廣泛的涉及相關(guān)知識(shí),但始終沒(méi)有深入研究。原因很簡(jiǎn)單,我認(rèn)為廣度可以決定深度,大學(xué)期間應(yīng)博學(xué),不宜專于細(xì)節(jié)。現(xiàn)在畢業(yè)了,我選擇了圖形學(xué)作為自己深入研究的方向。

關(guān)于圖形學(xué),我也算是初學(xué)者,也許,與大家不同的是,在深入研究之前,我做了充分的知識(shí)準(zhǔn)備,我計(jì)劃從點(diǎn)的繪制開始,實(shí)現(xiàn)一套完整的三維渲染流水線。朋友們,跟我一起學(xué)吧,讓我們披荊斬棘,一起攀上這座美麗的高峰!

下面,開始我們的第一步,創(chuàng)建一個(gè)windows下的窗口程序。

理論:

Windows 程序中,在寫圖形用戶界面時(shí)需要調(diào)用大量的標(biāo)準(zhǔn) Windows Gui 函數(shù)。其實(shí)這對(duì)用戶和程序員來(lái)說(shuō)都有好處,對(duì)于用戶,面對(duì)的是同一套標(biāo)準(zhǔn)的窗口,對(duì)這些窗口的操作都是一樣的,所以使用不同的應(yīng)用程序時(shí)無(wú)須重新學(xué)習(xí)操作。對(duì)程序員來(lái)說(shuō),這些 Gui 源代碼都是經(jīng)過(guò)了微軟的嚴(yán)格測(cè)試,隨時(shí)拿來(lái)就可以用的。當(dāng)然至于具體地寫程序?qū)τ诔绦騿T來(lái)說(shuō)還是有難度的。為了創(chuàng)建基于窗口的應(yīng)用程序,必須嚴(yán)格遵守規(guī)范。作到這一點(diǎn)并不難,只要用模塊化或面向?qū)ο蟮木幊谭椒纯伞?/span>

下面我就列出在桌面顯示一個(gè)窗口的幾個(gè)步驟:

  1. 得到您應(yīng)用程序的句柄(必需)
  2. 得到命令行參數(shù)(如果您想從命令行得到參數(shù),可選)
  3. 注冊(cè)窗口類(必需,除非您使用 Windows 預(yù)定義的窗口類,如 MessageBox dialog box
  4. 產(chǎn)生窗口(必需)
  5. 在桌面顯示窗口(必需,除非您不想立即顯示它)
  6. 刷新窗口客戶區(qū);
  7. 進(jìn)入無(wú)限的獲取窗口消息的循環(huán);
  8. 如果有消息到達(dá),由負(fù)責(zé)該窗口的窗口回調(diào)函數(shù)處理;
  9. 如果用戶關(guān)閉窗口,進(jìn)行退出處理。

相對(duì)于單用戶的 DOS 下的編程來(lái)說(shuō),Windows 下的程序框架結(jié)構(gòu)是相當(dāng)復(fù)雜的。但是 Windows DOS 在系統(tǒng)架構(gòu)上是截然不同的。Windows 是一個(gè)多任務(wù)的操作系統(tǒng),故系統(tǒng)中同時(shí)有多個(gè)應(yīng)用程序彼此協(xié)同運(yùn)行。這就要求 Windows 程序員必須嚴(yán)格遵守編程規(guī)范,并養(yǎng)成良好的編程風(fēng)格。

Windows 中的文本是一個(gè)GUI(圖形用戶界面)對(duì)象。每一個(gè)字符實(shí)際上是由許多的像素點(diǎn)組成,這些點(diǎn)在有筆畫的地方顯示出來(lái),這樣就會(huì)出現(xiàn)字符。這也是為什么我說(shuō)繪制字符,而不是寫字符。通常您都是在您應(yīng)用程序的客戶區(qū)繪制字符串(盡管您也可以在客戶區(qū)外繪制)。Windows 下的繪制字符串方法和 Dos 下的截然不同,在 Dos 下,您可以把屏幕想象成 85 x 25 的一個(gè)平面,而 Windows 下由于屏幕上同時(shí)有幾個(gè)應(yīng)用程序的畫面,所以您必須嚴(yán)格遵從規(guī)范。Windows 通過(guò)把每一個(gè)應(yīng)用程序限制在他的客戶區(qū)來(lái)做到這一點(diǎn)。當(dāng)然客戶區(qū)的大小是可變的,您隨時(shí)可以調(diào)整。

在您在客戶區(qū)繪制字符串前,您必須從 Windows 那里得到您客戶區(qū)的大小,確實(shí)您無(wú)法像在 DOS 下那樣隨心所欲地在屏幕上任何地方繪制,繪制前您必須得到 Windows 的允許,然后 Windows 會(huì)告訴您客戶區(qū)的大小,字體,顏色和其它 GUI 對(duì)象的屬性。您可以用這些來(lái)在客戶區(qū)繪制

什么是設(shè)備環(huán)境DC)呢? 它其實(shí)是由 Windows 內(nèi)部維護(hù)的一個(gè)數(shù)據(jù)結(jié)構(gòu)。一個(gè)設(shè)備環(huán)境和一個(gè)特定的設(shè)備相連。像打印機(jī)和顯示器。對(duì)于顯示器來(lái)說(shuō),設(shè)備環(huán)境和一個(gè)個(gè)特定的窗口相連。

設(shè)備環(huán)境中的有些屬性和繪圖有關(guān),像:顏色,字體等。您可以隨時(shí)改動(dòng)那些缺省值,之所以保存缺省值是為了方便。您可以把設(shè)備環(huán)境想象成是Windows 為您準(zhǔn)備的一個(gè)繪圖環(huán)境,而您可以隨時(shí)根據(jù)需要改變某些缺省屬性。

當(dāng)應(yīng)用程序需要繪制時(shí),您必須得到一個(gè)設(shè)備環(huán)境的句柄。通常有幾種方法。

  • WM_PAINT 消息中使用 call BeginPaint
  • 在其他消息中使用 call GetDC
  • call CreateDC 建立你自己的 DC

您必須牢記的是,在處理單個(gè)消息后你必須釋放設(shè)備環(huán)境句柄。不要在一個(gè)消息處理中獲得設(shè)備環(huán)境句柄,而在另一個(gè)消息處理中在釋放它。

我們?cè)?span>Windows 發(fā)送 WM_PAINT 消息時(shí)處理繪制客戶區(qū),Windows 不會(huì)保存客戶區(qū)的內(nèi)容,它用的是方法是重繪機(jī)制(譬如當(dāng)客戶區(qū)剛被另一個(gè)應(yīng)用程序的客戶區(qū)覆蓋),Windows 會(huì)把 WM_PAINT 消息放入該應(yīng)用程序的消息隊(duì)列。重繪窗口的客戶區(qū)是各個(gè)窗口自己的責(zé)任,您要做的是在窗口過(guò)程處理 WM_PAINT 的部分知道繪制什么和何如繪制。

您必須了解的另一個(gè)概念是無(wú)效區(qū)域Windows 把一個(gè)最小的需要重繪的正方形區(qū)域叫做無(wú)效區(qū)域。當(dāng) Windows 發(fā)現(xiàn)了一個(gè)無(wú)效區(qū)域后,它就會(huì)向該應(yīng)用程序發(fā)送一個(gè) WM_PAINT 消息,在 WM_PAINT 的處理過(guò)程中,窗口首先得到一個(gè)有關(guān)繪圖的結(jié)構(gòu)體,里面包括無(wú)效區(qū)的坐標(biāo)位置等。您可以通過(guò)調(diào)用BeginPaint 無(wú)效區(qū)有效,如果您不處理 WM_PAINT 消息,至少要調(diào)用缺省的窗口處理函數(shù) DefWindowProc ,或者調(diào)用 ValidateRect 無(wú)效區(qū)有效。否則您的應(yīng)用程序?qū)?huì)收到無(wú)窮無(wú)盡的 WM_PAINT 消息。

下面是響應(yīng)該消息的步驟:

  1. 取得設(shè)備環(huán)境句柄
  2. 繪制客戶區(qū)
  3. 釋放設(shè)備環(huán)境句柄

注意,您無(wú)須顯式地讓無(wú)效區(qū)有效,這個(gè)動(dòng)作由 BeginPaint 自動(dòng)完成。您可以在 BeginPaint Endpaint 之間,調(diào)用所有的繪制函數(shù)。幾乎所有的GDI 函數(shù)都需要設(shè)備環(huán)境的句柄作為參數(shù)。

 

內(nèi)容:

下面是我們簡(jiǎn)單的窗口程序的源代碼。在進(jìn)入復(fù)雜的細(xì)節(jié)前,我將提綱挈領(lǐng)地指出幾點(diǎn)要點(diǎn):

  1. 您應(yīng)當(dāng)把程序中要用到的所有常量和結(jié)構(gòu)體的聲明放到一個(gè)頭文件中,并且在源程序的開始處包含這個(gè)頭文件。這么做將會(huì)節(jié)省您大量的時(shí)間,也免得一次又一次的敲鍵盤。您也可以定義您自己的常量和結(jié)構(gòu)體,但最好把它們放到獨(dú)立的頭文件中。
  2. 在其它地方運(yùn)用頭文件中定義函數(shù)原型,常數(shù)和結(jié)構(gòu)體時(shí),要嚴(yán)格保持和頭文件中的定義一致,包括大小寫。在查詢函數(shù)定義時(shí),這將節(jié)約您大量的時(shí)間;
  3. 如果想詳細(xì)系統(tǒng)的學(xué)習(xí)Windows編程,可以參考《windows程序設(shè)計(jì)》,點(diǎn)擊下載
  4. 如果你的系統(tǒng)中沒(méi)有安裝VC 或不會(huì)使用VC,我準(zhǔn)備了精簡(jiǎn)版本,只有10MB左右,無(wú)需復(fù)雜操作,也能編譯本教程中的代碼,生成程序,點(diǎn)擊下載
  5. 如果你對(duì)下面的代碼視如天書,那么請(qǐng)先看《譚浩強(qiáng)C語(yǔ)言教程》,務(wù)必熟讀,點(diǎn)擊下載

 

 1/*------------------------------------------------------------------------
 2  HELLOWIN.CPP -- Displays "你好, 歡迎使用YM的圖形學(xué)教程!" in client area 
 3                 (c) Charles Petzold, 1998 
 4-----------------------------------------------------------------------*/
 
 5#include <windows.h>
 6
 7LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
 8 
 9int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
10                   PSTR szCmdLine, int iCmdShow)
11{
12static TCHAR szAppName[] = TEXT ("HelloWin") ;
13    HWND   hwnd ;
14    MSG    msg ;
15    WNDCLASS    wndclass ;
16    wndclass.style        = CS_HREDRAW | CS_VREDRAW ;
17    wndclass.lpfnWndProc  = WndProc ;
18    wndclass.cbClsExtra   = 0 ;
19    wndclass.cbWndExtra   = 0 ;
20    wndclass.hInstance    = hInstance ;
21    wndclass.hIcon        = LoadIcon (NULL, IDI_APPLICATION) ;
22    wndclass.hCursor      = LoadCursor (NULL, IDC_ARROW) ;
23    wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
24    wndclass.lpszMenuName = NULL ;
25    wndclass.lpszClassName= szAppName ;
26    RegisterClass (&wndclass);        
27    hwnd = CreateWindow( szAppName,      // window class name
28                   TEXT ("The Hello Program"),   // window caption
29                   WS_OVERLAPPEDWINDOW,  // window style
30                   CW_USEDEFAULT,// initial x position
31                   CW_USEDEFAULT,// initial y position
32                   CW_USEDEFAULT,// initial x size
33                   CW_USEDEFAULT,// initial y size
34                   NULL,         // parent window handle
35                   NULL,         // window menu handle
36                   hInstance,    // program instance handle
37                   NULL) ;      // creation parameters
38    ShowWindow (hwnd, iCmdShow) ;
39    UpdateWindow (hwnd) ;
40    while (GetMessage (&msg, NULL, 00))
41    {
42          TranslateMessage (&msg) ;
43          DispatchMessage (&msg) ;
44    }

45    return msg.wParam ;
46}

47LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
48{
49    HDC            hdc ;
50    PAINTSTRUCT     ps ;
51    RECT          rect ;
52    switch (message)
53    {
54    case   WM_PAINT:
55            hdc = BeginPaint (hwnd, &ps) ;
56            GetClientRect (hwnd, &rect) ;
57            DrawText (hdc, TEXT ("你好, 歡迎使用YM的圖形學(xué)教程! "), -1&rect,
58                   DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
59            EndPaint (hwnd, &ps) ;
60            return 0 ;
61    case   WM_DESTROY:
62            PostQuitMessage (0) ;
63            return 0 ;
64    }

65  return DefWindowProc (hwnd, message, wParam, lParam) ;
66}

67

 

 

分析:

看到一個(gè)簡(jiǎn)單的 Windows 程序有這么多行,您是不是有點(diǎn)想撤? 但是您必須要知道的是上面的大多數(shù)代碼都是模板而已,模板的意思即是指這些代碼對(duì)差不多所有標(biāo)準(zhǔn) Windows 程序來(lái)說(shuō)都是相同的。在寫 Windows 程序時(shí)您可以把這些代碼拷來(lái)拷去,當(dāng)然把這些重復(fù)的代碼寫到一個(gè)庫(kù)中也挺好。其實(shí)真正要寫的代碼集中在 WinMain 中。這和一些 C 編譯器一樣,無(wú)須要關(guān)心其它雜務(wù),集中精力于 WinMain 函數(shù)。唯一不同的是 C 編譯器要求您的源代碼有必須有一個(gè)函數(shù)叫 WinMain。否則 C 無(wú)法知道將哪個(gè)函數(shù)和有關(guān)的前后代碼鏈接。相對(duì)C,匯編語(yǔ)言提供了較大的靈活性,它不強(qiáng)行要求一個(gè)叫 WinMain 的函數(shù)。

下面我們開始分析,您可得做好思想準(zhǔn)備,這可不是一件太輕松的活。

HELLOWIN至少呼叫了18個(gè)Windows函數(shù)。下面以它們?cè)?span>HELLOWIN中出現(xiàn)的次序列出這些函數(shù)以及各自的簡(jiǎn)明描述:

  • LoadIcon 加載圖標(biāo)供程序使用。
  • LoadCursor 加載鼠標(biāo)光標(biāo)供程序使用。
  • GetStockObject 取得一個(gè)圖形對(duì)象(在這個(gè)例子中,是取得繪制窗口背景的畫刷對(duì)象)。
  • RegisterClass 為程序窗口注冊(cè)窗口類別。
  • MessageBox 顯示消息框。
  • CreateWindow 根據(jù)窗口類別建立一個(gè)窗口。
  • ShowWindow 在屏幕上顯示窗口。
  • UpdateWindow 指示窗口自我更新。
  • GetMessage 從消息隊(duì)列中取得消息。
  • TranslateMessage 轉(zhuǎn)譯某些鍵盤消息。
  • DispatchMessage 將消息發(fā)送給窗口消息處理程序。
  • PlaySound 播放一個(gè)聲音文件。
  • BeginPaint 開始繪制窗口。
  • GetClientRect 取得窗口顯示區(qū)域的大小。
  • DrawText 顯示字符串。
  • EndPaint 結(jié)束繪制窗口。
  • PostQuitMessage 在消息隊(duì)列中插入一個(gè)「退出程序」消息。
  • DefWindowProc 執(zhí)行內(nèi)定的消息處理。

這些函數(shù)均在Platform SDK文件中說(shuō)明,并在不同的表頭文件中聲明,其中絕大多數(shù)聲明在WINUSER.H中。

WinMain函數(shù)共有4個(gè)參數(shù):應(yīng)用程序的實(shí)例句柄,該應(yīng)用程序的前一實(shí)例句柄,命令行參數(shù)串指針和窗口如何顯示。Win32 沒(méi)有前一實(shí)例句柄的概念,所以第二個(gè)參數(shù)總為0。之所以保留它是為了和 Win16 兼容的考慮,在 Win16下,如果 hPrevInst NULL,則該函數(shù)是第一次運(yùn)行。特別注意:您不用必須申明一個(gè)名為 WinMain 函數(shù),事實(shí)上在這方面您可以完全作主,您甚至無(wú)須有一個(gè)和 WinMain 等同的函數(shù)。您只要把 WinMain 中的代碼拷到GetCommandLine 之后,其所實(shí)現(xiàn)的功能完全相同。在 WinMain 返回時(shí),產(chǎn)生一個(gè)返回值。然后在應(yīng)用程序結(jié)束時(shí)通過(guò) ExitProcess 函數(shù)把該返回碼傳遞給 Windows

 

 1    wndclass.style        = CS_HREDRAW | CS_VREDRAW ;
 2    wndclass.lpfnWndProc = WndProc ;
 3    wndclass.cbClsExtra   = 0 ;
 4    wndclass.cbWndExtra   = 0 ;
 5    wndclass.hInstance    = hInstance ;
 6    wndclass.hIcon        = LoadIcon (NULL, IDI_APPLICATION) ;
 7    wndclass.hCursor      = LoadCursor (NULL, IDC_ARROW) ;
 8    wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
 9    wndclass.lpszMenuName = NULL ;
10   wndclass.lpszClassName= szAppName ;
11   RegisterClass (&wndclass); 
12

上面幾行從概念上說(shuō)確實(shí)是非常地簡(jiǎn)單。只要幾行指令就可以實(shí)現(xiàn)。其中的主要概念就是窗口類(window class),一個(gè)窗口類就是一個(gè)有關(guān)窗口的規(guī)范,這個(gè)規(guī)范定義了幾個(gè)主要的窗口的元素,如:圖標(biāo)、光標(biāo)、背景色、和負(fù)責(zé)處理該窗口的函數(shù)。您產(chǎn)生一個(gè)窗口時(shí)就必須要有這樣的一個(gè)窗口類。如果您要產(chǎn)生不止一個(gè)同種類型的窗口時(shí),最好的方法就是把這個(gè)窗口類存儲(chǔ)起來(lái),這種方法可以節(jié)約許多的內(nèi)存空間。也許今天您不會(huì)太感覺(jué)到,可是想想以前 PC 大多數(shù)只有 1M 內(nèi)存時(shí),這么做是非常有必要的。如果您要定義自己的創(chuàng)建窗口類就必須:在一個(gè) WINDCLASS WINDOWCLASSEX 結(jié)構(gòu)體中指明您窗口的組成元素,然后調(diào)用 RegisterClass RegisterClass ,再根據(jù)該窗口類產(chǎn)生窗口。對(duì)不同特色的窗口必須定義不同的窗口類。 WINDOWS有幾個(gè)預(yù)定義的窗口類,譬如:按鈕、編輯框等。要產(chǎn)生該種風(fēng)格的窗口無(wú)須預(yù)先再定義窗口類了,只要包預(yù)定義類的類名作為參數(shù)調(diào)用 CreateWindow 即可。

WNDCLASS 中最重要的成員莫過(guò)于lpfnWndProc了。前綴 lpfn 表示該成員是一個(gè)指向函數(shù)的長(zhǎng)指針。在 Win32中由于內(nèi)存模式是 FLAT 型,所以沒(méi)有 near far 的區(qū)別。每一個(gè)窗口類必須有一個(gè)窗口過(guò)程,當(dāng) Windows 把屬于特定窗口的消息發(fā)送給該窗口時(shí),該窗口的窗口類負(fù)責(zé)處理所有的消息,如鍵盤消息或鼠標(biāo)消息。由于窗口過(guò)程差不多智能地處理了所有的窗口消息循環(huán),所以您只要在其中加入消息處理過(guò)程即可。下面我將要講解 WNDCLASSEX 的每一個(gè)成員

 1typedef struct tagWNDCLASS {
 2  UINT      style;
 3  WNDPROC   lpfnWndProc;
 4  int       cbClsExtra;
 5  int       cbWndExtra;
 6  HINSTANCE hInstance;
 7  HICON     hIcon;
 8  HCURSOR   hCursor;
 9  HBRUSH    hbrBackground;
10  LPCTSTR   lpszMenuName;
11  LPCTSTR   lpszClassName;
12}
 WNDCLASS, *PWNDCLASS;
13
14CreateWindow( szAppName,      // window class name
15                   TEXT ("The Hello Program"),   // window caption
16                   WS_OVERLAPPEDWINDOW,  // window style
17                   CW_USEDEFAULT,// initial x position
18                   CW_USEDEFAULT,// initial y position
19                   CW_USEDEFAULT,// initial x size
20                   CW_USEDEFAULT,// initial y size
21                   NULL,         // parent window handle
22                   NULL,         // window menu handle
23                   hInstance,    // program instance handle
24                   NULL) ;      // creation parameters
25

注冊(cè)窗口類后,我們將調(diào)用CreateWindow來(lái)產(chǎn)生實(shí)際的窗口。請(qǐng)注意該函數(shù)有11個(gè)參數(shù)。

 

 1HWND WINAPI CreateWindow(
 2  __in_opt  LPCTSTR lpClassName,
 3  __in_opt  LPCTSTR lpWindowName,
 4  __in      DWORD dwStyle,
 5  __in      int x,
 6  __in      int y,
 7  __in      int nWidth,
 8  __in      int nHeight,
 9  __in_opt  HWND hWndParent,
10  __in_opt  HMENU hMenu,
11  __in_opt  HINSTANCE hInstance,
12  __in_opt  LPVOID lpParam
13);
14

 

我們來(lái)仔細(xì)看一看這些的參數(shù):

  • lpClassName:(必須)。ASCIIZ形式的窗口類名稱的地址。可以是您自定義的類,也可以是預(yù)定義的類名。像上面所說(shuō),每一個(gè)應(yīng)用程序必須有一個(gè)窗口類。
  • lpWindowNameASCIIZ形式的窗口名稱的地址。該名稱會(huì)顯示在標(biāo)題條上。如果該參數(shù)空白,則標(biāo)題條上什么都沒(méi)有。
  • dwStyle:窗口的風(fēng)格。在此您可以指定窗口的外觀。可以指定該參數(shù)為零,但那樣該窗口就沒(méi)有系統(tǒng)菜單,也沒(méi)有最大化和最小化按鈕,也沒(méi)有關(guān)閉按鈕,那樣您不得不按Alt+F4 來(lái)關(guān)閉它。最為普遍的窗口類風(fēng)格是 WS_OVERLAPPEDWINDOW。 一種窗口風(fēng)格是一種按位的掩碼,這樣您可以用“or”把您希望的窗口風(fēng)格或起來(lái)。像 WS_OVERLAPPEDWINDOW 就是由幾種最為不便普遍的風(fēng)格或起來(lái)的。
  • XY: 指定窗口左上角的以像素為單位的屏幕坐標(biāo)位置。缺省地可指定為 CW_USEDEFAULT,這樣 Windows 會(huì)自動(dòng)為窗口指定最合適的位置。
  • nWidth nHeight: 以像素為單位的窗口大小。缺省地可指定為 CW_USEDEFAULT,這樣 Windows 會(huì)自動(dòng)為窗口指定最合適的大小。
  • hWndParent: 父窗口的句柄(如果有的話)。這個(gè)參數(shù)告訴 Windows 這是一個(gè)子窗口和他的父窗口是誰(shuí)。這和 MDI(多文檔結(jié)構(gòu))不同,此處的子窗口并不會(huì)局限在父窗口的客戶區(qū)內(nèi)。他只是用來(lái)告訴 Windows 各個(gè)窗口之間的父子關(guān)系,以便在父窗口銷毀是一同把其子窗口銷毀。在我們的例子程序中因?yàn)橹挥幸粋€(gè)窗口,故把該參數(shù)設(shè)為 NULL
  • hMenu WINDOWS菜單的句柄。如果只用系統(tǒng)菜單則指定該參數(shù)為NULL。回頭看一看WNDCLASSEX 結(jié)構(gòu)中的 lpszMenuName 參數(shù),它也指定一個(gè)菜單,這是一個(gè)缺省菜單,任何從該窗口類派生的窗口若想用其他的菜單需在該參數(shù)中重新指定。其實(shí)該參數(shù)有雙重意義:一方面若這是一個(gè)自定義窗口時(shí)該參數(shù)代表菜單句柄,另一方面,若這是一個(gè)預(yù)定義窗口時(shí),該參數(shù)代表是該窗口的 ID 號(hào)。Windows 是根據(jù)lpClassName 參數(shù)來(lái)區(qū)分是自定義窗口還是預(yù)定義窗口的。
  • hInstance: 產(chǎn)生該窗口的應(yīng)用程序的實(shí)例句柄。
  • lpParam: (可選)指向欲傳給窗口的結(jié)構(gòu)體數(shù)據(jù)類型參數(shù)的指針。如在MDI中在產(chǎn)生窗口時(shí)傳遞 CLIENTCREATESTRUCT 結(jié)構(gòu)的參數(shù)。一般情況下,該值總為零,這表示沒(méi)有參數(shù)傳遞給窗口。可以通過(guò)GetWindowLong 函數(shù)檢索該值。
 
1ShowWindow (hwnd, iCmdShow) ;
2UpdateWindow (hwnd) ;
調(diào)用CreateWindow成功后,會(huì)返回窗口句柄。我們必須保存該值以備后用。我們剛剛產(chǎn)生的窗口不會(huì)自動(dòng)顯示,所以必須調(diào)用 ShowWindow 來(lái)按照我們希望的方式來(lái)顯示該窗口。接下來(lái)調(diào)用 UpdateWindow 來(lái)更新客戶區(qū)。 

 

1while (GetMessage (&msg, NULL, 00))
2{
3     TranslateMessage (&msg) ;
4     DispatchMessage (&msg) ;
5}


這時(shí)候我們的窗口已顯示在屏幕上了。但是它還不能從外界接收消息。所以我們必須給它提供相關(guān)的消息。我們是通過(guò)一個(gè)消息循環(huán)來(lái)完成該項(xiàng)工作的。每一個(gè)模塊僅有一個(gè)消息循環(huán),我們不斷地調(diào)用 GetMessage Windows 中獲得消息。GetMessage 傳遞一個(gè) MSG 結(jié)構(gòu)體給 Windows ,然后 Windows 在該函數(shù)中填充有關(guān)的消息,一直到 Windows 找到并填充好消息后 GetMessage 才會(huì)返回。在這段時(shí)間內(nèi)系統(tǒng)控制權(quán)可能會(huì)轉(zhuǎn)移給其他的應(yīng)用程序。這樣就構(gòu)成了Win16 下的多任務(wù)結(jié)構(gòu)。如果 GetMessage 接收到 WM_QUIT 消息后就會(huì)返回 FALSE,使循環(huán)結(jié)束并退出應(yīng)用程序。TranslateMessage 函數(shù)是一個(gè)是實(shí)用函數(shù),它從鍵盤接受原始按鍵消息,然后解釋成 WM_CHAR,在把 WM_CHAR 放入消息隊(duì)列,由于經(jīng)過(guò)解釋后的消息中含有按鍵的 ASCII 碼,這比原始的掃描碼好理解得多。如果您的應(yīng)用程序不處理按鍵消息的話,可以不調(diào)用該函數(shù)。DispatchMessage 會(huì)把消息發(fā)送給負(fù)責(zé)該窗口過(guò)程的函數(shù)。

1return msg.wParam


如果消息循環(huán)結(jié)束了,退出碼存放在 MSG 中的 wParam中,您可以通過(guò)把它放到 eax 寄存器中傳給 Windows目前 Windows 沒(méi)有利用到這個(gè)結(jié)束碼,但我們最好還是遵從 Windows 規(guī)范已防意外。

 

1LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);


是我們的窗口處理函數(shù)。您可以隨便給該函數(shù)命名。其中第一個(gè)參數(shù) hWnd 是接收消息的窗口的句柄。message是接收的消息。注意message不是一個(gè) MSG 結(jié)構(gòu),其實(shí)上只是一個(gè) DWORD 類型數(shù)。Windows 定義了成百上千個(gè)消息,大多數(shù)您的應(yīng)用程序不會(huì)處理到。當(dāng)有該窗口的消息發(fā)生時(shí),Windows 會(huì)發(fā)送一個(gè)相關(guān)消息給該窗口。其窗口過(guò)程處理函數(shù)會(huì)智能的處理這些消息。wParam lParam 只是附加參數(shù),以方便傳遞更多的和該消息有關(guān)的數(shù)據(jù)。

 1switch (message)
 2{
 3    case   WM_PAINT:
 4            hdc = BeginPaint (hwnd, &ps) ;
 5            GetClientRect (hwnd, &rect) ;
 6            DrawText (hdc, TEXT ("你好, 歡迎使用YM的圖形學(xué)教程!"), -1&rect,
 7                   DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
 8            EndPaint (hwnd, &ps) ;
 9            return 0 ;
10    case   WM_DESTROY:
11            PostQuitMessage (0) ;
12            return 0 ;
13}

14    return DefWindowProc (hwnd, message, wParam, lParam) ;
15


上面可以說(shuō)是關(guān)鍵部分。這也是我們寫 Windows 程序時(shí)需要改寫的主要部分。此處您的程序檢查 Windows 傳遞過(guò)來(lái)的消息,如果是我們感興趣的消息則加以處理,處理完后,在 eax 寄存器中傳遞 0,否則必須調(diào)用 DefWindowProc,把該窗口過(guò)程接收到的參數(shù)傳遞給缺省的窗口處理函數(shù)。所有消息中您必須處理的是 WM_DESTROY,當(dāng)您的應(yīng)用程序結(jié)束時(shí) Windows 把這個(gè)消息傳遞進(jìn)來(lái),當(dāng)您的應(yīng)用程序解說(shuō)到該消息時(shí)它已經(jīng)在屏幕上消失了,這僅是通知您的應(yīng)用程序窗口已銷毀,您必須自己準(zhǔn)備返回 Windows 。在此消息中您可以做一些清理工作,但無(wú)法阻止退出應(yīng)用程序。如果您要那樣做的話,可以處理 WM_CLOSE 消息。在處理完清理工作后,您必須調(diào)用 PostQuitMessage,該函數(shù)會(huì)把 WM_QUIT 消息傳回您的應(yīng)用程序,而該消息會(huì)使得 GetMessage 返回,并在將返回值設(shè)置0,然后會(huì)結(jié)束消息循環(huán)并退回 WINDOWS。您可以在您的程序中調(diào)用 DestroyWindow 函數(shù),它會(huì)發(fā)送一個(gè) WM_DESTROY 消息給您自己的應(yīng)用程序,從而迫使它退出。

特別注意:下面討論的是我們以后的課程的核心部分

1 HDC            hdc ;
2 PAINTSTRUCT     ps ;
3 RECT          rect ;
4


這些局部變量由處理 WM_PAINT 消息中的 GDI 函數(shù)調(diào)用。hdc 用來(lái)存放調(diào)用 BeginPaint 返回的設(shè)備環(huán)境句柄。ps 是一個(gè) PAINTSTRUCT 數(shù)據(jù)類型的變量。通常您不會(huì)用到其中的許多值,它由 Windows 傳遞給 BeginPaint,在結(jié)束繪制后再原封不動(dòng)的傳遞給 EndPaintrect 是一個(gè) RECT 結(jié)構(gòu)體類型參數(shù),它的定義如下:

1typedef struct _RECT {
2  LONG left;
3  LONG top;
4  LONG right;
5  LONG bottom;
6}
 RECT, *PRECT;
7


 left top 是正方形左上角的坐標(biāo)。right bottom 是正方形右下角的坐標(biāo)。客戶區(qū)的左上角的坐標(biāo)是 x=0y=0,這樣對(duì)于 x=0y=10 的坐標(biāo)點(diǎn)就在它的下面。

1      hdc = BeginPaint (hwnd, &ps) ;
2      GetClientRect (hwnd, &rect) ;
3      DrawText (hdc, TEXT ("你好, 歡迎使用YM的圖形學(xué)教程!"), -1&rect,
4                   DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
5       EndPaint (hwnd, &ps) ;
6


在處理 WM_PAINT 消息時(shí),您調(diào)用BeginPaint函數(shù),傳給它一個(gè)窗口句柄和未初始化的 PAINTSTRUCT 型參數(shù)。調(diào)用成功后在 eax 中返回設(shè)備環(huán)境的句柄。下一次,調(diào)用 GetClientRect 以得到客戶區(qū)的大小,大小放在 rect 中,然后把它傳給 DrawTextDrawText 的語(yǔ)法如下:

1int DrawText(
2  HDC hDC, 
3  LPCTSTR lpString, 
4  int nCount, 
5  LPRECT lpRect, 
6  UNIT uFormat);
7


 DrawText是一個(gè)高層的調(diào)用函數(shù)。它能自動(dòng)處理像換行、把文本放到客戶區(qū)中間等這些雜事。所以您只管集中精力繪制字符串就可以了。我們會(huì)在下一課中講解低一層的函數(shù) TextOut,該函數(shù)在一個(gè)正方形區(qū)域中格式化一個(gè)文本串。它用當(dāng)前選擇的字體、顏色和背景色。它處理?yè)Q行以適應(yīng)正方形區(qū)域。它會(huì)返回以設(shè)備邏輯單位度量的文本的高度,我們這里的度量單位是像素點(diǎn)。讓我們來(lái)看一看該函數(shù)的參數(shù):

  • hdc設(shè)備環(huán)境的句柄。
  • lpString:要顯示的文本串,該文本串要么以NULL結(jié)尾,要么在nCount中指出它的長(zhǎng)短。
  • nCount:要輸出的文本的長(zhǎng)度。若以NULL結(jié)尾,該參數(shù)必須是-1
  • lpRect: 指向要輸出文本串的正方形區(qū)域的指針,該方形必須是一個(gè)裁剪區(qū),也就是說(shuō)超過(guò)該區(qū)域的字符將不能顯示。
  • uFormat:指定如何顯示。我們可以用 or 把以下標(biāo)志或到一塊:
    • DT_SINGLELINE:是否單行顯示。
    • DT_CENTER:是否水平居中。
    • DT_VCENTER :是否垂直居中。

 

結(jié)束繪制后,必須調(diào)用 EndPaint 釋放設(shè)備環(huán)境的句柄。好了,現(xiàn)在我們把繪制文本串的要點(diǎn)總結(jié)如下:

  1. 必須在開始和結(jié)束處分別調(diào)用 BeginPaint EndPaint
  2. BeginPaint EndPaint 之間調(diào)用所有的繪制函數(shù);
  3. 如果在其它的消息處理中重新繪制客戶區(qū),您可以有兩種選擇:
    1)用GetDCReleaseDC代替BeginPaintEndPaint
    2)調(diào)用InvalidateRectUpdateWindow讓客戶區(qū)無(wú)效,這將迫使WINDOWSWM_PAINT放入應(yīng)用程序消息隊(duì)列,從而使得客戶區(qū)重繪。

 

posted on 2011-01-22 14:49 姚明 閱讀(1209) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 原創(chuàng)教程
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美精品一区二区三区高清aⅴ| 一区二区在线视频观看| 国产一区二区电影在线观看| 久久久xxx| 欧美大片免费观看在线观看网站推荐| 亚洲视频自拍偷拍| 久久av在线| 一区二区高清视频在线观看| 午夜精品视频在线观看一区二区| 在线日韩av片| 亚洲男人的天堂在线aⅴ视频| 亚洲国产高清一区| 亚洲免费视频成人| 亚洲美女中文字幕| 久久久国产精品一区| 中日韩男男gay无套| 久久久国产一区二区三区| 性欧美办公室18xxxxhd| 中文在线一区| 欧美激情第二页| 亚洲在线观看免费| 日韩午夜免费视频| 欧美一区成人| 亚洲综合欧美| 暖暖成人免费视频| 亚洲国产一区二区三区a毛片| 亚洲电影免费| 日韩视频免费观看高清在线视频 | 1000精品久久久久久久久 | 午夜在线成人av| 蜜臀久久99精品久久久画质超高清| 欧美福利一区| 欧美在线地址| 欧美日韩在线影院| 亚洲欧洲偷拍精品| 欧美一区二区三区男人的天堂 | 午夜视频在线观看一区| 欧美1级日本1级| 国产亚洲在线观看| 午夜电影亚洲| 99国产欧美久久久精品| 免费不卡中文字幕视频| 韩国女主播一区| 欧美一级视频一区二区| 亚洲高清av| 欧美怡红院视频一区二区三区| 欧美另类一区| 亚洲国产精品欧美一二99| 欧美在线看片| 亚洲综合第一| 国产精品久久久爽爽爽麻豆色哟哟| 亚洲国产一区二区精品专区| 久久久噜久噜久久综合| 亚洲伊人色欲综合网| 欧美性猛交xxxx乱大交蜜桃| 亚洲国产日韩欧美在线动漫| 美国十次了思思久久精品导航| 亚洲欧美日韩综合| 国产女主播一区| 欧美一区二区福利在线| 亚洲精品中文字幕在线| 久久一区二区三区四区| 欧美中文字幕视频| 黑丝一区二区| 免费亚洲一区二区| 久久午夜羞羞影院免费观看| 国产专区一区| 欧美夫妇交换俱乐部在线观看| 久久精品99无色码中文字幕| 国产专区一区| 亚洲第一在线综合网站| 欧美α欧美αv大片| 亚洲精品免费在线观看| 亚洲精品久久| 国产九区一区在线| 久久天天综合| 欧美不卡在线视频| 99热免费精品| 在线午夜精品自拍| 国产视频久久久久| 欧美成人久久| 欧美日韩一区二区视频在线观看| 9色精品在线| 亚洲欧美韩国| 亚洲成人在线| 亚洲最新视频在线播放| 国产精品白丝黑袜喷水久久久| 亚洲一区日韩在线| 久久成年人视频| 亚洲黄色精品| 日韩视频―中文字幕| 国产偷久久久精品专区| 亚洲高清免费视频| 国产精品久久久99| 欧美成人精品在线播放| 欧美日韩在线另类| 裸体一区二区三区| 国产精品成人观看视频国产奇米| 久久综合九色综合欧美就去吻| 免费成年人欧美视频| 午夜精品在线视频| 免费观看成人www动漫视频| 亚洲综合国产| 欧美成人首页| 欧美亚洲专区| 欧美日韩一区三区| 亚洲第一精品夜夜躁人人躁| 国产精品视频1区| 亚洲第一偷拍| 在线激情影院一区| 午夜天堂精品久久久久| 一区二区三区精品久久久| 久久激五月天综合精品| 亚洲欧美国产精品桃花| 免费永久网站黄欧美| 久久久噜噜噜| 国产伦精品一区二区三区视频孕妇 | 久久免费黄色| 欧美精品在欧美一区二区少妇| 欧美在线91| 欧美日韩伦理在线免费| 欧美激情久久久久久| 国产一区二区在线观看免费播放 | 免费久久99精品国产| 欧美伊人精品成人久久综合97| 欧美日本亚洲韩国国产| 欧美91大片| 狠狠色噜噜狠狠狠狠色吗综合| 一区二区欧美日韩| 在线亚洲电影| 欧美日韩一区二区三区四区五区| 亚洲国产毛片完整版| 亚洲欧洲日本在线| 欧美寡妇偷汉性猛交| 亚洲高清免费视频| 亚洲毛片在线看| 欧美日韩国产成人精品| 亚洲人成人99网站| 亚洲精品一区二区三区在线观看| 久久久久久久999精品视频| 欧美在线视频导航| 国产手机视频一区二区| 午夜国产精品视频| 久久久久久久91| 依依成人综合视频| 免费亚洲电影| av不卡免费看| 先锋影音国产精品| 国产一区二区欧美| 两个人的视频www国产精品| 欧美激情中文字幕一区二区| 亚洲精品午夜精品| 欧美午夜不卡| 亚洲欧美日韩国产| 免费成人在线观看视频| 亚洲日本免费| 国产精品盗摄一区二区三区| 亚洲一级在线| 毛片精品免费在线观看| 日韩视频久久| 日韩视频―中文字幕| 欧美精品在线免费观看| 一区二区高清在线观看| 久久国产一区| 亚洲精品你懂的| 国产精品国产三级国产aⅴ无密码| 亚洲欧美久久| 亚洲国产欧美日韩精品| 亚洲欧美日韩国产中文| 红桃视频亚洲| 欧美日韩伦理在线| 久久久999成人| 一本色道久久精品| 蜜桃av噜噜一区| 亚洲一区二区三区777| 加勒比av一区二区| 国产精品成人免费精品自在线观看| 亚洲影视中文字幕| 亚洲春色另类小说| 欧美一区影院| 一区二区欧美日韩| 影音先锋久久| 国产精品一区二区久久国产| 欧美不卡视频一区| 久久激情网站| 亚洲性视频网站| 亚洲欧美另类在线| 亚洲国产精品久久久久秋霞影院| 欧美午夜精品久久久久久孕妇| 久久综合国产精品台湾中文娱乐网| 夜夜夜久久久| 最新国产成人在线观看| 久久视频这里只有精品| 亚洲一区二区精品视频| 亚洲欧洲在线看| 狠狠色伊人亚洲综合成人| 国产精品美女主播在线观看纯欲| 欧美高清在线一区| 欧美成年人网站| 麻豆精品在线视频|