程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Win32開發入門(11) 使用控件——先來耍一下按鈕

Win32開發入門(11) 使用控件——先來耍一下按鈕

編輯:關於C++

用戶通過控件與應用程序交互,在吹牛之前,先介紹一個工具,這是官方的工具,使用它,你可以 預覽常用控件的外觀、樣式,以及對控進行操作時接收和發送哪些消息。下載地址如下:

http://www.microsoft.com/en-us/download/details.aspx?id=4635

我們可以把控件當 成特殊的一類窗口,所以,創建控件與創建窗口一樣,使用CreateWindow或CreateWindowEx函數,不過 ,在窗口樣式上面記得用上以下兩位帥哥:

a、WS_CHILD:控件是放在我們的窗口上的,自然要 作為窗口的子窗口,WS_CHILDWINDOW也一樣,為了節約幾個字母,用WS_CHILD吧。

b、 WS_VISIBLE:既然要使用控件,自然要讓別人看得見。要想別人稱贊你老婆漂亮,當然要先讓別人見一 見你老婆了,哈哈,不要想歪了。

理論的東西,怎麼說都是抽象的,咱們還是“所見即所得” 吧。那麼,到底在啥時候創建控件合適一點呢?一種方法是在WinMain方法中創建,把CreateWindow函 數的hWndParent設置為窗口的句柄。

俺這裡用第二種方法,我們知道,在窗口創建後,顯示之 前,即CreateWindow函數返回之前,我們會收到WM_CREATE消息,我們響應它的號召,艱苦奮斗創建一 個按鈕。

case WM_CREATE:     
    {     
        //創建按鈕     
        HWND hButton = CreateWindow(L"Button", L"有種就來點擊我!", WS_VISIBLE | WS_CHILD 

| BS_PUSHBUTTON,     
            35, 45, 160, 65, hwnd, NULL, hg_app, NULL);     
    }     
    return 0;

hg_app是我定義的一個全局變量,當前應用程序的句柄(HINSTANCE類型)。

然後,運行一下,先看看效果再說吧。

接下來,新的問題來了,按鈕我是創建了,但怎麼響應用戶點擊呢?其實,這按鈕與菜單項 一樣,單擊用戶與她“親密”接觸後,我們的WindowProc會收到WM_COMMAND消息,和菜單一樣。

wParam的低字節位表示ID號,高字節位表示控件通知,比如用戶單擊了按鈕,通知碼為 BN_CLICKED,這樣我們就可以了解到用戶具體對按鈕干了什麼。

lParam中保存了控件的句柄。

問題是,怎麼設置控件的ID?我們看看CreateWindow的文檔介紹。

HWND WINAPI 

CreateWindow(     
  _In_opt_  LPCTSTR lpClassName,     
  _In_opt_  LPCTSTR lpWindowName,     
  _In_      DWORD dwStyle,     
  _In_      int x,     
  _In_      int y,     
  _In_      int nWidth,     
  _In_      int nHeight,     
  _In_opt_  HWND hWndParent,     
  _In_opt_  HMENU hMenu,     
  _In_opt_  HINSTANCE hInstance,     
  _In_opt_  LPVOID lpParam     
);

hMenu [in, optional]

Type: HMENU

A handle to a menu, or specifies a child -window identifier depending on the window style. For an overlapped or pop-up window, hMenu identifies the menu to be used with the window; it can be NULL if the class menu is to be used. For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.

 

簡單地說,控件通常不需要菜單,所以,可以用這個參數來設置控件 的ID,反正hMenu閒著也沒事干,就給個ID它玩玩。ID號是一個整數,不過為了可讀性,一般是聲明一 個宏,其實我們在資源編輯器中使用的資源ID(如IDM_FUCK)就是在resource.h中定義的宏的,既然叫 ID了,你就知道它的值不要重復。

我們也來模擬一下,在文件的前面(#include...後)也聲明 三個宏,分別標識三個按鈕。

#define IDB_ONE     3301     
#define IDB_TWO     3302     
#define IDB_THREE   3303

然後創建三個按鈕:

case WM_CREATE:     
 {     
  //創建三個按鈕     
  CreateWindow(L"Button", L"按鈕一", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,     
   35, 10, 120, 60, hwnd, (HMENU)IDB_ONE, hg_app, NULL);     
  CreateWindow(L"Button", L"按鈕二", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,     
   35, 80, 120, 60, hwnd, (HMENU)IDB_TWO, hg_app, NULL);     
  CreateWindow(L"Button", L"按鈕三", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,     
   35, 150, 120, 60, hwnd, (HMENU)IDB_THREE, hg_app, NULL);     
 }     
 return 0;

然後我們來響應WM_COMMAND消息。

case WM_COMMAND:     
    {     
        switch(LOWORD(wParam))     
        {     
        case IDB_ONE:     
            MessageBox(hwnd, L"您點擊了第一個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
            break;     
        case IDB_TWO:     
            MessageBox(hwnd, L"您點擊了第二個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
            break;     
        case IDB_THREE:     
            MessageBox(hwnd, L"您點擊了第三個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
            break;     
        default:     
            break;     
        }     
    }     
    return 0;

看看效果。

這時候,我希望,當我點擊了按鈕後,按鈕上的文本變成“按鈕X已點擊”,該怎麼做呢? Windows系統是基於消息機制的,所以,首先想到,向控件發送消息,要改變控件相關的文本,應當發 送WM_SETTEXT消息。

我們把上面的代碼改一下。

case WM_COMMAND:     
    {     
        switch(LOWORD(wParam))     
        {     
        case IDB_ONE:     
            //MessageBox(hwnd, L"您點擊了第一個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
            SendMessage((HWND)lParam, WM_SETTEXT, (WPARAM)NULL, (LPARAM)L"第一個按鈕已點擊

");     
            break;     
        case IDB_TWO:     
            //MessageBox(hwnd, L"您點擊了第二個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
            SendMessage((HWND)lParam, WM_SETTEXT, (WPARAM)NULL, (LPARAM)L"第二個按鈕已點擊

");     
            break;     
        case IDB_THREE:     
            //MessageBox(hwnd, L"您點擊了第三個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
            SendMessage((HWND)lParam, WM_SETTEXT, (WPARAM)NULL, (LPARAM)L"第三個按鈕已點擊

");     
            break;     
        default:     
            break;     
        }     
    }     
    return 0;

前面我們知道,WM_COMMAND消息的lParam保存控件的句柄,所以,我們傳給 SendMessage的第一個參數是操作目標的句柄,注意,這裡不要傳WindowProc回調中的參數,因為我們 現在要操作的對象是按鈕,不是窗口,WindowProc傳進到的句柄是指我們注冊的窗口,因為我們在 WNDCLASS中已經設定了該WindowProc函數。

要對按鈕進行操作,應當使用WM_COMMAND的 lParam中包含的值,強制轉換為HWND。

運行結果如下圖所示。

完整的示例如下:

#include <Windows.h>     
#include <WinNT.h>     
//#include "resource.h"     
         
#define IDB_ONE     3301     
#define IDB_TWO     3302     
#define IDB_THREE   3303     
         
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);     
         
LPCWSTR lps_cl = L"MyApp";//類名     
LPCWSTR wd_text = L"超級應用";//窗口標題     
HINSTANCE hg_app;//全局實例句柄     
         
int WINAPI wWinMain(HINSTANCE hThisApp,     
    HINSTANCE hPrevApp,     
    LPWSTR lpCmd,     
    int nShow)     
{     
    WNDCLASSEX wc = { };     
    wc.cbSize = sizeof(WNDCLASSEX);     
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;     
    wc.hInstance = hThisApp;     
    wc.lpfnWndProc = (WNDPROC)WindowProc;     
    wc.lpszClassName = lps_cl;     
    wc.style = CS_HREDRAW | CS_VREDRAW;     
    RegisterClassEx(&wc);     
    HWND hwnd = CreateWindowEx(WS_EX_WINDOWEDGE,     
                    lps_cl,     
                    wd_text,     
                    WS_OVERLAPPEDWINDOW,     
                    20,     
                    25,     
                    400,     
                    300,     
                    NULL,     
                    NULL,     
                    hThisApp,     
                    NULL);     
    if(hwnd == NULL)     
        return -1;     
    ShowWindow(hwnd, nShow);     
    UpdateWindow(hwnd);     
    hg_app = hThisApp;     
         
    MSG msg;     
    while(GetMessage(&msg,NULL,0,0))     
    {     
        TranslateMessage(&msg);     
        DispatchMessage(&msg);     
    }     
    return 0;     
}     
         
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)     
{     
    switch(msg)     
    {     
    case WM_DESTROY:     
        PostQuitMessage(0);     
        return 0;     
    case WM_CREATE:     
        {     
            //創建三個按鈕     
            CreateWindow(L"Button", L"按鈕一", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,     
                35, 10, 160, 60, hwnd, (HMENU)IDB_ONE, hg_app, NULL);     
            CreateWindow(L"Button", L"按鈕二", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,     
                35, 80, 160, 60, hwnd, (HMENU)IDB_TWO, hg_app, NULL);     
            CreateWindow(L"Button", L"按鈕三", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,     
                35, 150, 160, 60, hwnd, (HMENU)IDB_THREE, hg_app, NULL);     

        }     
        return 0;     
    case WM_COMMAND:     
        {     
            switch(LOWORD(wParam))     
            {     
            case IDB_ONE:     
                //MessageBox(hwnd, L"您點擊了第一個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
                SendMessage((HWND)lParam, WM_SETTEXT, (WPARAM)NULL, (LPARAM)L"第一個按鈕已

點擊");     
                break;     
            case IDB_TWO:     
                //MessageBox(hwnd, L"您點擊了第二個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
                SendMessage((HWND)lParam, WM_SETTEXT, (WPARAM)NULL, (LPARAM)L"第二個按鈕已

點擊");     
                break;     
            case IDB_THREE:     
                //MessageBox(hwnd, L"您點擊了第三個按鈕。", L"提示", MB_OK | 

MB_ICONINFORMATION);     
                SendMessage((HWND)lParam, WM_SETTEXT, (WPARAM)NULL, (LPARAM)L"第三個按鈕已

點擊");     
                break;     
            default:     
                break;     
            }     
        }     
        return 0;     
    default:     
        return DefWindowProc(hwnd,msg,wParam,lParam);     
    }     
    return 0;     
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved