程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> 第一章:Windows 圖形界面之 創建窗口

第一章:Windows 圖形界面之 創建窗口

編輯:.NET實例教程

1.1 了解窗口

 

在圖形化基於視窗的應用程序裡,窗口就是屏幕上一塊可視區域,應用程序的窗口包括標題欄,菜單欄,Windows系統菜單,最小化按鈕,最大化按鈕,恢復按鈕,關閉按鈕,可改變大小的邊框,窗口客戶區,垂直滾動條,水平滾動條.

窗口客戶區是應用程序顯示輸出部分

 

1.2 窗口的創建

 

1.21 創建Win32工程和MessageBox函數

Windows 應用程序的主函數是:

int APIENTRY WinMain(HINSTANCE hInstance,      //應用程序的實例句柄

                                   HINSTANCE hPrevInstance,  //Win16留下的廢物,不用參數

                                   LPSTR lpCmdLine,                   命令行參數

                                   int  nCmdShow)                //主窗口初始化的顯示方式  

 

 

Windows 彈出對話框的函數是:

::MessageBox(HWND hwnd,    //一個窗口句柄,指定的對話框屬於哪一個窗口所有

                                                        //設為NULL,表示沒有窗口擁有該對話框

              LPCSTR lpText,   //對話框的正文

                       LPCSTR lpCaption,  //對話框的標題

                       UINT uType)      //

對話框顯示按鈕種類和行為

nType 指示了對話框顯示按鈕的種類和行為,可以設成如下的值:

1:  MB_OK 確定按鈕

2:  MB_OKCANCEL  包括兩個按鈕:確定和取消按鈕

3:  MB_ABORTRETRYIGNORE  包括三個按鈕:終止,調試和忽略

4:  MB_YESNOCANCEL  包括三個按鈕:,否和取消

5:  MB_YESNO     是和否按鈕

6:  MB_RETRYCANCEL 重試和取消按鈕

7:  MB_ICONHAND  一個停止標志圖標

8:  MB_ICONQUESTION  一個詢問標志圖標

9:  MB_ICONEXCLAMATION 一個感歎號圖標

10: MB_DEFBUTTON1  第一個按鈕是選中按鈕

11: MB_DEFBUTTON2  第二個按鈕是選中按鈕

12: MB_DEFBUTTON3  第三個按鈕是選中按鈕

13: MB_DEFBUTTON4  第四個按鈕是選中按鈕

MessageBox 函數返回被選中按鈕的ID,ID號為一個整形數值,這個宏在WINUSER.H中定義:

ID = ID + 按鈕單詞

如果確定按鈕被選中,將返回:IDOK

 

示例代碼:

#include <Windows.h>

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

     int nSet = ::MessageBox(NULL,"Hello world","標題",MB_YESNOCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON3);

     if(nSet == IDYES)

     {

         ::MessageBox(NULL,"用戶選擇了是按鈕","標題",MB_OK);

     }

     else if(nSet == IDNO)

     {

         ::MessageBox(NULL,"用戶選擇了否按鈕","標題",MB_OK);

     }

     else if(nSet == IDCANCEL)

     {

         ::MessageBox(NULL,"用戶選擇了取消按鈕","標題",MB_OK);

     }

     return 0;

}

 

 

 

1.22 Windows 的消息驅動

創建窗口後,就要對窗口的行為負責,比如用戶拖動窗口時,應跟隨鼠標移動這個窗口.如果不這麼做,程序將失去窗口界面的友好性,但是,如何知道用戶在窗口上的動作呢

是操作系統告訴程序的,Windows不斷向程序發送消息,通知用戶在窗口上的動作

Windows向程序發送消息時,它調用程序中的一個函數,這個函數稱為消息處理函數

>,
它是一個自定義的回調函數,原形如下:

LRESULT CALLBACK WinProc(HWND hwnd,  //窗口句柄

UINT message, //消息ID

WPARAM wParam, //消息參數,其值取決於消息//的類型

LPARAM lParam) //消息參數,其值取決於消息

//的類型

 

例如,一般的應程序接受到 WM_CLOSE 消息時會試圖銷毀自己的窗口,下面代碼為了關閉了記事本程序,向它的主窗口發送了 WM_CLOSE 消息,運行這個程序之前請先新建一個文本文檔,然後再打開這個文本文檔.

 

#include <Windows.h>

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

     HWND hwnd;

     BOOL bStart = FALSE;

     while(bStart == FALSE)

     {

         //查找標題為"新建文本文檔.txt - 記事本"的窗口

         hwnd = ::FindWindow("Notepad","新建文本文檔.txt - 記事本");

         if(hwnd != NULL)

         {

              //向窗口發送WM_CLOSE 消息

              ::SendMessage(hwnd,WM_CLOSE,0,0);

              ::MessageBox(NULL,"新建文本文檔.txt - 記事本窗口已關閉","消息提示",MB_OK);

              bStart = TRUE;

         }

         else    {

              ::MessageBox(NULL,"請先啟動新建文本文檔.txt - 記事本窗口","消息提示",MB_OK);  

         }

     }

     return 0;

}

 

以上是一個應用程序向另一個應用程序發送窗口的過程,系統向應用程序發送消息的過程是類似的,系統為應用程序傳遞所有輸入到它的各個窗口,每個窗口都關聯一個消息處理函數,消息處理函數處理輸入,然後再將控制權交給系統

 

1.2.3 創建第一個窗口.

下面是一個最簡單的窗口程序源代碼,它的作用是彈出一個典型的 Windows 程序窗口,這些代碼可以做為今後用 API Windows 程序的基本框架

#include <Windows.h>

 

//消息處理函數原形

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

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

     char *szClassName = "WndClass";

     WNDCLASSEX wndclass;

     //用描述主窗口的參數填充WNDCLASSEX 結構

     wndclass.cbSize = sizeof(wndclass);  //定義結構的大小

     wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;  //定義窗口樣式

     wndclass.lpfnWndProc = WndProc;  //指定本窗口的消息處理函數

     wndclass.cbClsExtra = 0;    //沒有額外的類內存

     wndclass.cbWndExtra = 0;   //沒有額外的窗口內存

     wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);   //使用默認的圖標

     wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);     //使用默認的光標

     wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);  //定義窗口的背景顏色為灰色

     wndclass.hInstance = hInstance;  //實例句柄

     wndclass.lpszClassName = szClassName;   //窗口類名稱

     wndclass.lpszMenuName = NULL;    //不使用菜單

>

     wndclass.hIconSm = NULL;   //沒有類的小圖標

 

     //注冊窗口類

     ::RegisterClassEx(&wndclass);

 

     //創建主窗口

     HWND hwnd = ::CreateWindowEx(0,  //不定義擴展樣式

                                     szClassName,  //類名

                                     "Hello world",  //窗口標題

                                     WS_OVERLAPPEDWINDOW,  //窗口風格

                                     CW_USEDEFAULT,   //默認的窗口X 軸坐標

                                     CW_USEDEFAULT,   //默認的窗口Y 軸坐標

                                     CW_USEDEFAULT,   //默認的窗口寬度

                                     CW_USEDEFAULT,   //默認的窗口高度

                                     NULL,   //沒有父窗口句柄

                                     NULL,   //沒有菜單句柄

                                     hInstance,  //程序實例句柄

                                     NULL);     //沒有用戶數據

 

     if(hwnd == NULL)

     {

         ::MessageBox(NULL,"創建窗口出錯","error",MB_ICONHAND);

     return -1;

     }

 

     //顯示窗口

     ::ShowWindow(hwnd,nCmdShow);

 

     //刷新窗口客戶區

     ::UpdateWindow(hwnd);

 

     //從消息隊列中取出消息,交給消息處理函數處理,直到GetMessage 函數返回FALSE ,結束消息循環

     MSG msg;

     while(::GetMessage(&msg,NULL,0,0))

     {

         //轉化鍵盤消息

         ::TranslateMessage(&msg);

 

         //將消息發送給消息處理函數

         ::DispatchMessage(&msg);

     }

 

     return msg.wParam;

}

 

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)

{

     char *szText = "My first window process ";

     HDC hdc;  //聲明設備環境句柄

     PAINTSTRUCT ps;

     switch(msg)

     {

     case WM_PAINT:  //窗口客戶區需要重畫

         {

              //使無效的客戶區變得有效,並取得設備環境句柄

              hdc = ::BeginPaint(hwnd,&ps);

              ::TextOut(hdc,0,0,szText,strlen(szText));

    

    ::EndPaint(hwnd,&ps);

              return 0;

         }

     case WM_DESTROY:  //正在銷毀窗口

         {

              //向消息隊列投遞一個WM_QUIT 消息,促使GetMessage 函數返回0,結束消息循環

              ::PostQuitMessage(0);

              return 0;

         }

     }

 

     // 將我們不處理的消息交給系統做默認處理

     return ::DefWindowProc(hwnd,msg,wParam,lParam);

}

分析以上程序,可以得出在桌面上創建一個窗口的具體步驟

(1)    注冊窗口類(RegisterClassEx)

(2)    創建窗口(CeateWindowEx)

(3)    在桌面上顯示窗口(ShowWindow)

(4)    更新窗口客戶區(UpdateWindow)

(5)    進入無限的消息獲取和處理消息的循環,首先是獲取消息(GetMessage),如果有消息到達,則通過 DispatchMessage 函數將消息發送到指定的消息處理函數 WndProc;

 

 

創建窗口的知識要點:

(1).指定窗口類的樣式:

wndclass.style = CS_HREDRAW | CS_VREDRAW;

這句代碼指定了如果窗口寬度或高度改變了就重畫整個窗口, WINUSER.H 中定義了窗口類的全部可用樣式,可以組合使用各種樣式

(2)指定窗口客戶區重畫時使用的畫刷

wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);

這句代碼指定使用 Windows 預定義的白色背景畫刷,也可以自己創建一個畫刷對象以便指定喜歡的顏色為窗口背景色,下面的代碼將窗口的背景色改為了黃.色

Wndclass.hbrBackground = (HBRUSH)::GetSolidBrush(RGB(255,255,0));

…………………

………………….

::DeleteObject(wndclass.hbrBackground);  //最後別忘記在程序結束之前刪除創建的刷子釋放資源

(3)指定窗口的風格

CreateWindows 第四個參數指定了窗口的風格,下面列出了一些最常見的風格定義,它們是以 WS 為前辍的預定義的值

WS_BORDER  創建一個單邊框的窗口

WS_CAPTION  創建一個有標題框的窗口(包括WS_BORDER風格)

WS_CHILD   創建一個子窗口,這個風格不能與 WS_POPVP 風格合用

WS_DISABLED  創建一個初始狀態為禁止的子窗口,一個禁止狀態的窗口不能接受來自用戶的輸入信息

WS_DLGFRAME 創建一個帶對話框邊框風格的窗口,這種風格的窗口不能帶有標題條

WS_HSCROLL   創建一個有水平滾動條的窗口

WS_VSCROOL  創建一個有垂直滾動條的窗口

WS_ICONIC    創建一個初始狀態為最小化的窗口, WS_MINIMIZE 風格相同

WS_MAXIMIZE  創建一個初始狀態為最大化的窗口,該風格不能與 WS_EX_CONTEXTHELP 風格同時出現,同時必須指定 WS_SYSMENU 風格

WS_OVERLAPPED  產生一個層疊窗口,一個層疊的窗口有一個標題條和一個邊框, WS_TILED 風格相同

WS_OVERLAPPEDWINDOW 創建一個具有 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,WS_THICKFRAME, WS_MINIMIZEBOX,WS_MAXMIZEBOX 風格的層疊窗口

WS_POPUP 創建一個彈出式窗口,該風格不能與WS_CHLD 風格同時使用

WS_POPUPWINDOW 創建一個具有 WS_BORDER, WS_POPUP, WS_SYSMENU, 風格的窗口,WS_CAPTION WS_POPUPWINDOW 必須同時使用才能使窗口可見

WS_SIZEBOX 創建一個可調邊框的窗口, WS_THICKFRAME 風格相同

WS_SYSMENU 創建一個在標題條上帶有窗口菜單的窗口,必須同時設定 WS_CAPTION 風格

 

WS_THICKFRAME 創建一個具有可調邊框的窗口, WS_SIZEBOX 風格相同

WS_VISBLE 創建一個初始狀態為可見的窗口

 

(4)消息隊列 MSG 結構

Windows 為每個線程維護了一個消息隊列,每當有消息進入時,Windows 就利用GetMessage 函數調用線程的消息隊列來填充 MSG 結構,這個結構定義了消息的所有屬性

Typedef struct tagMSG

{

       HWND hwnd;    //消息要發往的窗口句柄

       UINT message;   //消息標識符,WM_開頭的預定義值

       WPARAM wParam;  //消息參數之一

       LPARAM lParam;    //消息參數之二

       DWord time;       //消息放入消息隊列的時間

       POINT pt;    //這是一個POINT 數據結構,表示消息放入消息隊列時的鼠標位置

}MSG,  &PMSG;v

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