C++/SDK界面开发总结


Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

这年代用C++/SDK开发界面的不多了,不是入门研究那绝壁是情怀,不过这东西还是有用,虽然麻烦了点,但可以使生成的exe文件非常小,对于一些对exe文件大小以及响应速度非常在乎的来说,这还是很好的选择
为避免误人子弟,这儿贴几个关键字,对于开发Windows窗体程序来说,这些都是不错的选择,1为个人最推荐使用的,2为其次,以此类推

  1. WinForm/WPF:这个就强大了,两种界面开发模式几乎可以满足在任何条件下的需要,并且C#程序可以在Linux下运行,在Windows下几乎无敌,只是响应比SDK界面稍微慢点,目测是几十毫秒的延迟
  2. wxWidgets:跨平台、强大的界面库,相对于Qt来说是优点是完全无限制,缺点是用的人并没Qt多,开发者社区人少
  3. UILib:强大的DuiLib的升级版,优点是小巧、免费,缺点是只支持Windows平台,另外由于DuiLib作者不参与维护后,建立的UiLib维护机制相当散乱,相当于一堆高手参与维护但基本是自己维护自己的
  4. MFC:对于新手入门来说,这就是麻烦C;对于用过几年MFC的来说,能用MFC就绝不用SDK;个人感觉,这库还是相当不错的,至少没SDK麻烦
  5. Qt:跨平台、强大的界面库,唯一瑕疵是使用LGPL开源协议,只可使用动态链接库,对于静态链接要收费
  6. WTL:从入门角度来说,WTL比MFC稍微简单点,效果比MFC炫酷,不过这个很久没更新咯,最新版本貌似是07年的
  7. CB++/Delphi:这个实际上就是C++ Builder自带的界面库VCL,开发环境一般为C++ Builder 6或者RAD Studio,对于新手来说开发界面相当轻松,不过有一个很大的问题,C++ Builder 6有时候会出BUG,RAD Studio与Visual Studio不兼容。另外Delphi 7开发界面还是很不错的,用的也是VCL界面库,但我不喜欢Pascal的语法,所以也没深入研究这个

下面开始总结C++/SDK开发窗体程序
1、窗口
主要通过新建资源窗口实现布局,调用就通过 DialogBox 和 CreateDialog 实现界面的显示。其中 DialogBox 为模态窗口, CreateDialog 为非模态窗口,简要说说区别:
模态窗口:在没有父窗口的时候,调用 DialogBox 实现显示窗口。系统在 DialogBox 这儿卡住,直到窗口关闭后继续以下的代码。
非模态窗口:调用 CreateDialog 之后,代码继续往下执行。如果没有父窗口,则执行 GetMessage TranslateMessage DispatchMessage 这几个代码,如果存在父窗口,则只需要进入父窗口的消息循环,子窗口也可以进行消息循环响应。
2、控件
Windows 下面的控件种类繁多,在此我简要介绍几种的使用
2.1、托盘图标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#pragma once
#ifndef __HNOTIFYICON_HPP__
#define __HNOTIFYICON_HPP__
 
#include <Windows.h>
#include <Shellapi.h>
#pragma comment(lib, "Shell32.lib")
 
class hNotifyIcon {
    NOTIFYICONDATA h_nid;
 
public:
    hNotifyIcon (HWND hWnd, HICON hIcon, LPCTSTR lpTitle, LPCTSTR lpTips = NULL, int iTimeOut = 5, UINT uWndMsg = WM_USER + 1) {
        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 = uWndMsg;
        this->h_nid.hBalloonIcon = this->h_nid.hIcon = hIcon;
        lstrcpy ((LPTSTR)this->h_nid.szTip, (lpTips ? lpTips : lpTitle));
        lstrcpy ((LPTSTR)this->h_nid.szInfoTitle, lpTitle);
        this->h_nid.uTimeout = iTimeOut;
    }
 
    ~hNotifyIcon () {
        if (this->IsShow ()) this->Hide ();
    }
 
    BOOL Show () {
        if (this->IsShow ()) return TRUE;
        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 Hide () {
        this->h_nid.uFlags = NULL;
        return Shell_NotifyIcon (NIM_DELETE, &this->h_nid);
    }
 
    BOOL Message (LPCTSTR lpMsg, UINT niif_InfoWarningError) {
        this->h_nid.dwInfoFlags = niif_InfoWarningError;
        lstrcpy (this->h_nid.szInfo, lpMsg);
        return Shell_NotifyIcon (NIM_MODIFY, &this->h_nid);
    }
 
    BOOL IsShow () {
        return this->h_nid.uFlags;
    }
};
 
#endif //__HNOTIFYICON_HPP__

实现上很简单,和MFC类似,对显示、隐藏、发送泡泡通知等功能进行了封装,需要使用时直接new一个对象出来,简单调用几下就完了。
2.2、ListView / ListCtrl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//风格
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,也就是所谓的分页控件
分两步,第一步是初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
#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消息

1
2
3
4
5
6
7
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、任务栏进度条
这个的实现比较麻烦,我放在云盘,需要的点击链接 http://pan.baidu.com/s/1gdmx2hX
这个主要在Win8+中,开启了相应的透明界面风格后,可以直接在任务栏上面程序图标这儿显示进度条,非常方便用户的查看
2.5、其他Windows常用控件
写一行代码:

1
#include <windowsx.h>

然后点进去,其他该有的都有了,比如RadioButton、CheckBox等等。并不代表所有的都有,SDK界面开发等待着你的发掘。
3、Manifest描述符
3.1、XP美化
对于SDK和MFC程序来说,在XP、Vista等古老的系统上,这个美化功能相当有效果,在Win7上也可以用。具体方法参见 http://blog.csdn.net/fawdlstty/article/details/7858031
xp.manifest代码:

1
2
3
4
5
6
7
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

3.2、权限描述符
有些代码可能需要较高权限才能运行,这儿提供一个管理员权限描述符,具体效果为,(如果没有签名,那么)程序运行前提示需要管理员权限,程序图标右下角出现特权标识

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="">
<assemblyIdentity version="1.0.0.0" name=".add"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
    </security>
</trustInfo>
</asmv1:assembly>

4、C++/SDK 调用 Gdiplus
有了标准控件,总不能没有绘图吧?GDI太渣,又麻烦又复杂又不支持png还有锯齿。我在这儿简要说说如何引用Gdiplus。
首先,头文件和库别少,命名空间可以不引用,看个人爱好

1
2
3
#include <Gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;

然后,下面代码霸气甩进WinMain开头

1
2
3
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

最后,下面代码霸气甩进WinMain返回前

1
GdiplusShutdown(gdiplusToken);

介绍的差不多了。 Win32 博大精深,如有遗漏之处欢迎指正。

发布者

fawdlstty

又一只萌萌哒程序猿~~

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注