對於不習慣用MFC的程序員來說,寫界面應該是一個頭疼的事情了。調用duilib等開源界面庫的不討論,本文主要說說Windows的原生界面功能開發,作爲一篇總結,幫助新手入門。
1、窗口
主要通過新建資源窗口實現佈局,調用就通過 DialogBox 和 CreateDialog 實現界面的顯示。其中 DialogBox 爲模態窗口, CreateDialog 爲非模態窗口,簡要說說區別:
模態窗口:在沒有父窗口的時候,調用 DialogBox 實現顯示窗口。系統在 DialogBox 這兒卡住,直到窗口關閉後繼續以下的代碼。
非模態窗口:調用 CreateDialog 之後,代碼繼續往下執行。如果沒有父窗口,則執行 GetMessage TranslateMessage DispatchMessage 這幾個代碼,如果存在父窗口,則只需要進入父窗口的消息循環,子窗口也可以進行消息循環響應。
2、控件
Windows 下面的控件種類繁多,在此我簡要介紹幾種的使用
2.1、托盤圖標
//
// 文件:notifyicon.h
// 類:hNotifyIcon
// 主要功能:實現系統托盤圖標設置
//
#pragma once
#include <Shellapi.h>
class hNotifyIcon {
NOTIFYICONDATA h_nid;
public:
hNotifyIcon (HWND hWnd, HICON hIcon, LPCTSTR lpTitle, LPCTSTR lpTips = NULL, int iTimeOut = 5);
~hNotifyIcon ();
BOOL Show ();
BOOL Hide ();
BOOL Message (LPCTSTR lpMsg, UINT niif_InfoWarningError);
BOOL IsShow ();
};
//
// 文件:notifyicon.cpp
// 類:hNotifyIcon
// 主要功能:實現系統托盤圖標設置
//
#include "notifyicon.h"
#pragma comment(lib, "Shell32.lib")
hNotifyIcon::hNotifyIcon (HWND hWnd, HICON hIcon, LPCTSTR lpTitle, LPCTSTR lpTips, int iTimeOut) {
this->h_nid.cbSize = sizeof(NOTIFYICONDATA);
this->h_nid.hWnd = hWnd;
this->h_nid.uID = GetTickCount ()&0xFFFF;
this->h_nid.dwState = this->h_nid.dwStateMask = 0;
this->h_nid.uCallbackMessage = WM_USER+1;
this->h_nid.hBalloonIcon = this->h_nid.hIcon = hIcon;
if (lpTips)
lstrcpy ((LPTSTR)this->h_nid.szTip, lpTips);
else
lstrcpy ((LPTSTR)this->h_nid.szTip, lpTitle);
lstrcpy ((LPTSTR)this->h_nid.szInfoTitle, lpTitle);
this->h_nid.uTimeout = iTimeOut;
}
hNotifyIcon::~hNotifyIcon () {
if (this->IsShow ())
this->Hide ();
}
BOOL hNotifyIcon::Show () {
this->h_nid.uFlags = NIF_ICON|NIF_INFO|NIF_MESSAGE;
BOOL bRet = (BOOL) Shell_NotifyIcon (NIM_ADD, &this->h_nid);
this->h_nid.uFlags = NIF_INFO;
this->h_nid.dwInfoFlags = NIIF_INFO;
return bRet;
}
BOOL hNotifyIcon::Hide () {
this->h_nid.uFlags = NULL;
return (BOOL) Shell_NotifyIcon (NIM_DELETE, &this->h_nid);
}
BOOL hNotifyIcon::Message (LPCTSTR lpMsg, UINT niif_InfoWarningError) {
this->h_nid.dwInfoFlags = niif_InfoWarningError;
lstrcpy (this->h_nid.szInfo, lpMsg);
return (BOOL) Shell_NotifyIcon (NIM_MODIFY, &this->h_nid);
}
BOOL hNotifyIcon::IsShow () {
return (BOOL)this->h_nid.uFlags;
}
實現上很簡單,和MFC類似,對顯示、隱藏、發送泡泡通知等功能進行了封裝,需要使用時直接new一個對象出來,簡單調用幾下就完了。
2.2、ListView / ListCtrl//風格
DWORD dwStyle = ListView_GetExtendedListViewStyle(hList);
dwStyle |= LVS_EX_FULLROWSELECT;//選中整行
dwStyle |= LVS_EX_CHECKBOXES;//複選框
ListView_SetExtendedListViewStyle(hList, dwStyle);
//添加標頭
LV_COLUMN lc;
lc.mask = LVCF_TEXT | LVCF_WIDTH;
lc.cchTextMax = MAX_PATH;
lc.cx = 100;
lc.pszText = TEXT("列1");
ListView_InsertColumn(hList, 0, &lc);
lc.cx = 100;
lc.pszText = TEXT("列2");
ListView_InsertColumn(hList, 1, &lc);
……
//添加行
LVITEM li;
li.mask = LVIF_TEXT;
li.cchTextMax = MAX_PATH;
li.iSubItem = 0;
li.iItem = 0;//插入第幾行,從0開始
li.pszText = TEXT("列1");
ListView_InsertItem(hList, &li);
ListView_SetItemText(hList, li.iItem, 1, TEXT("列2"));
……
li.iItem = 1;
li.pszText = TEXT("列1");
ListView_InsertItem(hList, &li);
ListView_SetItemText(hList, li.iItem, 1, TEXT("列2"));
……
……
ListView / ListCtrl 的使用就方便多了,一大批 ListView_ 開頭的函數,任君選擇。
2.3、TabCtrl,也就是所謂的分頁控件
分兩步,第一步是初始化
#include <CommCtrl.h>
hwndTab = GetDlgItem();
hwndChild[0] = CreateDialog();
hwndChild[1] = CreateDialog();
TCITEM ti = { 0 };
ti.mask = TCIF_TEXT;
ti.cchTextMax = MAX_PATH;
ti.pszText = TEXT("tab1");
TabCtrl_InsertItem(hwndTab, 0, &ti);
ti.pszText = TEXT("tab2");
TabCtrl_InsertItem(hwndTab, 1, &ti);
第二步,處理WM_NOTIFY消息case WM_NOTIFY:
if (((LOWORD(wParam)) == IDC_TAB_MAIN) && (((LPNMHDR)lParam)->code == TCN_SELCHANGE))
{
for(int i=0; i<n; i++)
ShowWindow(hwndChild[i], SW_HIDE);
ShowWindow(hwndChild[TabCtrl_GetCurSel(hwndTab)], SW_SHOW);
}
break;
簡單方便。2.4、任務欄進度條
這個的實現比較麻煩,我放在雲盤,需要的點此下載
有兩個壓縮包,組件可以直接拿來用,源碼可以看看實現方法。另外,XP和Vista就不要試了,系統都沒有這個接口的。
2.5、其他Windows常用控件
寫一行代碼:
#include <windowsx.h>
然後點進去,其他該有的都有了,比如RadioButton、CheckBox等等。並不代表所有的都有,SDK界面開發等待着你的發掘。3、C++/SDK 調用 Gdiplus
有了標準控件,總不能沒有繪圖吧?GDI太渣,又麻煩又複雜又不支持png還有鋸齒。我在這兒簡要說說如何引用Gdiplus。
首先,頭文件和庫別少,命名空間可以不引用,看個人愛好
#include <Gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
然後,下面代碼霸氣甩進WinMain開頭
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
最後,下面代碼霸氣甩進WinMain返回前GdiplusShutdown(gdiplusToken);
介紹的差不多了。 Win32 博大精深,如有遺漏之處歡迎指正。