天天看點

windows sdk 資源和對話框建立

資源

概念

  • 資源:所有除代碼以外的東西都可稱為資源
  • ID:SDK所有添加的資源都可以設定唯一的ID
    • 若用字元串命名資源ID,需要字元串外加入雙引号("")
    • 可用指定API将資源ID轉換為對應指針 宏函數

      MAKEINTRESOURCE(MN_EDIT) // ID轉指針

帶資源的EXE檔案生成流程

windows sdk 資源和對話框建立

WM_COMMAND在視窗菜單程式中使用

// Win32Test.cpp : 定義應用程式的入口點。
//

#include "stdafx.h"
#include "Win32Test.h"
#include "resource.h"

void ShowErrorMessage()
{
  LPVOID lpMsgBuf;

  //将錯誤碼轉化為錯誤資訊,參數可以抄MSDN
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR)&lpMsgBuf,
    0,
    NULL
    );
  // Process any inserts in lpMsgBuf.
  // ...
  // 彈出錯誤提示視窗.
  MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONINFORMATION);
  // Free the buffer.
  LocalFree(lpMsgBuf);
}


LRESULT CALLBACK MyWindowPro
(HWND hwnd,     // 視窗句柄
UINT uMsg,      // 消息辨別
WPARAM wParam,  // 附加在消息上的參數
LPARAM lParam   // 附加在消息上的參數
)
{
  switch (uMsg)
  {  
  case WM_COMMAND:
  {
                   //高位判斷通知類型如果來自菜單,則為0, 如果來自快捷鍵,則為1
                   WORD wFrom = HIWORD(wParam);

                   //低位儲存菜單\快捷鍵的ID
                   WORD wID = LOWORD(wParam);

                   //菜單
                   if (wFrom == 0)
                   {
                     switch (wID)
                     {
                     case IDM_OPEN:
                       MessageBox(hwnd, TEXT("打開菜單"), NULL, MB_OK);
                       break;

                     case IDM_CLSOE:
                       MessageBox(hwnd, TEXT("關閉菜單"), NULL, MB_OK);
                       break;

                     default:
                       break;
                     }
                   }
                   else if (wFrom == 1)
                   {
                     switch (wID)
                     {
                     case IDA_ALT_O:
                       MessageBox(hwnd, TEXT("打開菜單"), NULL, MB_OK);
                       break;

                     case IDA_ALT_C:
                       MessageBox(hwnd, TEXT("關閉菜單"), NULL, MB_OK);
                       break;

                     default:
                       break;
                     }
                   }
                   break;
  }
  //點選關閉視窗會發送WM_CLOSE消息
  case WM_CLOSE:
  {
                 int nRet = MessageBox(hwnd, TEXT("是否退出"), TEXT("詢問"), MB_OKCANCEL);
                 if (nRet == IDCANCEL)//取消關閉
                 {
                   return 0;
                 }
                 else
                 {
                   //摧毀視窗發送WM_DESTROY消息
                   DestroyWindow(hwnd);
                 }

                 break;
  }
  case WM_DESTROY:
  {
                   //向消息隊列投遞WM_QUIT消息 WM_QUIT使消息循環退出,程式退出。
                   PostQuitMessage(0);
                   break;
  }
  default:
    break;
  }
  //系統預設處理消息視窗函數
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

//句柄可以了解為辨別ID,如視窗句柄就表示這個辨別這個視窗的唯一ID
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,//應用程式目前執行個體的句柄
                     _In_opt_ HINSTANCE hPrevInstance,//應用程式的先前執行個體的句柄
                     _In_ LPTSTR    lpCmdLine,//指向應用程式指令行的字元串的指針
                     _In_ int       nCmdShow)//指明視窗如何顯示,查msdn幫助文檔,有各種宏
{

  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW; //預設風格,視窗尺寸被修改後重畫視窗
  wc.lpfnWndProc = MyWindowPro; //視窗回調
  wc.cbClsExtra = 0; //視窗類的額外空間 
  wc.cbWndExtra = 0; //視窗執行個體的額外空間
  wc.hInstance = hInstance;
  wc.hIcon = NULL; //圖示
  wc.hCursor = NULL; //光标
  wc.hbrBackground = (HBRUSH)(COLOR_HIGHLIGHT);//背景
  wc.lpszMenuName = MAKEINTRESOURCE(IDM_TEST);//菜單
  wc.lpszClassName = TEXT("MyWindow");

  //加載菜單
  HMENU hMenu = LoadMenu(hInstance, TEXT("testmenu"));

  ATOM nRet = RegisterClass(&wc);
  if (nRet == 0)
  {
    ShowErrorMessage();
  }

  //建立視窗執行個體
  HWND hWnd = CreateWindow(
    TEXT("MyWindow"), //視窗類名
    TEXT("Hello World"), //視窗标題
    WS_OVERLAPPEDWINDOW, //重疊視窗
    CW_USEDEFAULT, CW_USEDEFAULT, //預設坐标
    CW_USEDEFAULT, CW_USEDEFAULT,//預設長和寬
    NULL, //沒有父視窗
    NULL, //加載菜單
    hInstance,//main函數的執行個體句柄
    NULL//暫時不用,(LPVOID)0x87654093,可用來做參數标記
    );
  if (hWnd == NULL)
  {
    ShowErrorMessage();
  }

  //顯示視窗
  ShowWindow(hWnd, SW_SHOW);

  //更新視窗
  UpdateWindow(hWnd);


  MSG msg;
  //消息循環
  //加載快捷鍵
  HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDA_TEST));
  while (GetMessage(&msg, NULL, 0, 0) != 0)
  {
    //轉換WM_KEYDOWN消息為快捷鍵消息
    if (!TranslateAccelerator(hWnd, hAccel, &msg))
    {
      //将keydown消息轉換為字元消息
      TranslateMessage(&msg);

      //派發消息到對應的視窗過程函數
      DispatchMessage(&msg);
    }
  }
  return 0;
}
           

概念

對話框是一種特殊的視窗,用來在使用者界面中向使用者顯示資訊,或者在需要的時候獲得使用者的輸入響應。

對話框三要素

  1. 編輯對話框模闆資源(CTRL+T 可預覽建立的對話框)
  2. 實作對話框過程函數
  3. 建立對話框示例

非模态對話框和模态對話框

聯系

建立時都會發送VM_INITDIALOG消息

差別

  • 建立函數不同
//建立模态對話框
DialogBox(g_hInstance,
  MAKEINTRESOURCE(DLG_TEST),//對話框ID
  hwnd,
  ModDialogProc);//對話框過程函數
  
//建立非模态對話框
CreateDialog(g_hInstance,
  MAKEINTRESOURCE(DLG_TEST),//對話框ID
  hwnd,
  ModDialogProc);//對話框過程函數

           
  • 銷毀函數不同
//銷毀模态對話框
EndDialog(hwndDlg, 0);
  
//銷毀非模态對話框
DestroyWindow(hwndDlg);

           
  • 對話框實作原理不同
//模态對話框建立時會調用此函數,禁止父視窗接受滑鼠鍵盤操作
EnableWindow(g_hWnd, false);

//模态對話框銷毀時會調用此函數,允許父視窗接受滑鼠鍵盤操作
EnableWindow(g_hWnd, true);
           
  • 對話框顯示方式不同
//非模态對話框建立完,需要調指定函數才可顯示
HWND hWnd = CreateDialog(g_hInstance,
  MAKEINTRESOURCE(DLG_TEST),
  hwnd, 
  ModlessDialogProc);

ShowWindow(hWnd, SW_SHOW);
           

建立對話框代碼 

// Win32Test.cpp : 定義應用程式的入口點。
//

#include "stdafx.h"
#include "Win32Test.h"
#include "resource.h"

/* 全局變量                                                                     */
/************************************************************************/
HINSTANCE g_hInstance = NULL;
HWND g_hWnd = NULL;

void ShowErrorMessage()
{
  LPVOID lpMsgBuf;

  //将錯誤碼轉化為錯誤資訊,參數可以抄MSDN
  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR)&lpMsgBuf,
    0,
    NULL
    );
  // Process any inserts in lpMsgBuf.
  // ...
  // 彈出錯誤提示視窗.
  MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONINFORMATION);
  // Free the buffer.
  LocalFree(lpMsgBuf);
}


/************************************************************************/
/* 對話框處理函數                                                                     */
/************************************************************************/
BOOL CALLBACK ModDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch (uMsg)
  {
  //  //建立顯示對話框之前觸發的消息
  //case  WM_INITDIALOG:
  //  //允許父視窗接受滑鼠鍵盤操作
  //  EnableWindow(g_hWnd, TRUE);
  //  break;

  case WM_CLOSE:
    //模态對話框銷毀使用EndDialog
    EndDialog(hwndDlg, 0);
    break;

  default:
    break;
  }
  return FALSE;
}

//非模态對話框的處理函數
BOOL CALLBACK ModlessDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch (uMsg)
  {
  把非模态對話框修為模态對話框
  //case  WM_INITDIALOG:
  //  //允許父視窗接受滑鼠鍵盤操作
  //  EnableWindow(g_hWnd, FALSE);
  //  break;

  case WM_CLOSE:
    //非模态對話框銷毀使用DestroyWindow
    DestroyWindow(hwndDlg);

    break;

  default:
    break;
  }
  return FALSE;
}

LRESULT CALLBACK MyWindowPro
(HWND hwnd,     // 視窗句柄
UINT uMsg,      // 消息辨別
WPARAM wParam,  // 附加在消息上的參數
LPARAM lParam   // 附加在消息上的參數
)
{
  switch (uMsg)
  {  
  case WM_COMMAND:
  {
                   //高位判斷通知類型如果來自菜單,則為0, 如果來自快捷鍵,則為1
                   WORD wFrom = HIWORD(wParam);

                   //低位儲存菜單\快捷鍵的ID
                   WORD wID = LOWORD(wParam);

                   //菜單
                   if (wFrom == 0)
                   {
                     switch (wID)
                     {
                     case IDM_MODE_DIALOG:
                     {
                                           //建立對話框
                                           DialogBox(g_hInstance,
                                             MAKEINTRESOURCE(IDD_DIALOG1),
                                             hwnd,
                                             ModDialogProc);
                                           break;
                     }
                      

                     case IDM_DIALOG:
                     {
                                      //建立非模态對話框
                                      HWND hWnd = CreateDialog(g_hInstance,
                                        MAKEINTRESOURCE(IDD_DIALOG1),
                                        hwnd,
                                        ModlessDialogProc);

                                      ShowWindow(hWnd, SW_SHOW);
                                      break;
                     }
                       
                     default:
                       break;
                     }
                   }
      
                   break;
  }
  //點選關閉視窗會發送WM_CLOSE消息
  case WM_CLOSE:
  {
                 int nRet = MessageBox(hwnd, TEXT("是否退出"), TEXT("詢問"), MB_OKCANCEL);
                 if (nRet == IDCANCEL)//取消關閉
                 {
                   return 0;
                 }
                 else
                 {
                   //摧毀視窗發送WM_DESTROY消息
                   DestroyWindow(hwnd);
                 }

                 break;
  }
  case WM_DESTROY:
  {
                   //向消息隊列投遞WM_QUIT消息 WM_QUIT使消息循環退出,程式退出。
                   PostQuitMessage(0);
                   break;
  }
  default:
    break;
  }
  //系統預設處理消息視窗函數
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

//句柄可以了解為辨別ID,如視窗句柄就表示這個辨別這個視窗的唯一ID
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,//應用程式目前執行個體的句柄
                     _In_opt_ HINSTANCE hPrevInstance,//應用程式的先前執行個體的句柄
                     _In_ LPTSTR    lpCmdLine,//指向應用程式指令行的字元串的指針
                     _In_ int       nCmdShow)//指明視窗如何顯示,查msdn幫助文檔,有各種宏
{

  g_hInstance = hInstance;

  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW; //預設風格,視窗尺寸被修改後重畫視窗
  wc.lpfnWndProc = MyWindowPro; //視窗回調
  wc.cbClsExtra = 0; //視窗類的額外空間 
  wc.cbWndExtra = 0; //視窗執行個體的額外空間
  wc.hInstance = hInstance;
  wc.hIcon = NULL; //圖示
  wc.hCursor = NULL; //光标
  wc.hbrBackground = (HBRUSH)(COLOR_HIGHLIGHT);//背景
  wc.lpszMenuName = MAKEINTRESOURCE(IDM_TEST);//菜單
  wc.lpszClassName = TEXT("MyWindow");

  //加載菜單
  HMENU hMenu = LoadMenu(hInstance, TEXT("testmenu"));

  ATOM nRet = RegisterClass(&wc);
  if (nRet == 0)
  {
    ShowErrorMessage();
  }

  //建立視窗執行個體
  HWND hWnd = CreateWindow(
    TEXT("MyWindow"), //視窗類名
    TEXT("Hello World"), //視窗标題
    WS_OVERLAPPEDWINDOW, //重疊視窗
    CW_USEDEFAULT, CW_USEDEFAULT, //預設坐标
    CW_USEDEFAULT, CW_USEDEFAULT,//預設長和寬
    NULL, //沒有父視窗
    NULL, //加載菜單
    hInstance,//main函數的執行個體句柄
    NULL//暫時不用,(LPVOID)0x87654093,可用來做參數标記
    );
  if (hWnd == NULL)
  {
    ShowErrorMessage();
  }
  g_hWnd = hWnd;
  //顯示視窗
  ShowWindow(hWnd, SW_SHOW);

  //更新視窗
  UpdateWindow(hWnd);


  MSG msg;
  //消息循環
  //加載快捷鍵
  HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDA_TEST));
  while (GetMessage(&msg, NULL, 0, 0) != 0)
  {
    //轉換WM_KEYDOWN消息為快捷鍵消息
    if (!TranslateAccelerator(hWnd, hAccel, &msg))
    {
      //将keydown消息轉換為字元消息
      TranslateMessage(&msg);

      //派發消息到對應的視窗過程函數
      DispatchMessage(&msg);
    }
  }
  return 0;
}
           

繼續閱讀