文号
t78381
阅读
6367
回复
3
收藏
1
【Win32编程】对话框程序,开启所有的通用控件
2015/12/26
IP:四川
目前来说,创建基于对话框的程序,Win32工程基本都能满足要求。现在MFC体积膨胀太厉害了,并且MFC的主要用途是编写框架程序,用它写基于对话框的程序有点杀鸡用牛刀了,其实大部分应用环境下用Win32就够了。Visual Studio 2015对话框设计器里共有28种通用控件可以在Win32工程中使用。

使用这个程序模板,可以开启对话框设计器里的所有通用控件。显然,以下两种控件是不可用的:
1.MFC增强控件(没加载MFC库)
2.ActiveX控件(实现起来太复杂)

如果以后又想加入ActiveX控件了怎么办?用原生方法的话太麻烦,因为添加ActiveX控件需要自己实现各种容器接口,WebBrowser这种复杂的控件的代码量更是可观的,我从网上找了一个例程,数了一下代码至少700行,其中一大半是无用代码。既然我们用Win32的目的是摆脱MFC,回去用MFC显然不划算。目前来看,向Win32工程添加ActiveX控件支持的最简单的办法还是用ATL。

ATL的CAxWindow和CAxDialogImpl可以支持ActiveX控件和包含ActiveX控件的对话框。使用这两个类必须要声明一个CComModule的全局变量以初始化环境,不然加载会失败。(一般使用CAxWindow手动创建,因为现在Visual Studio 2015不允许在非MFC对话框里添加ActiveX控件)

链接器指令:
1.链接comctl32.lib
2.通过/manifestdependency开关指定使用6.x版本的comctl32.dll,而不是默认的5.82版,不然会显示为2000样式,很多功能没有

显示对话框之前:
1.SetProcessDPIAware——设置DPI兼容(对话框是矢量界面,高DPI显示基本没什么问题)
2.CoInitalize——初始化COM环境
3.InitCommonControls——链接comctl32.dll(其实这只是一个空函数,只是告诉链接器一定要链接comctl32.lib而已)
4.InitNetworkAddressControl——加载NetworkAddress控件(吐槽:一个破文本框也要加载?)
5.LoadLibrary(L"riched20.dll")——加载RichEdit2.0控件

对话框退出之后:
1.FreeLibrary——卸载RichEdit2.0控件
2.CoUnintialize——卸载COM环境

#include "stdafx.h"
#include "resource.h"
                                      
// 链接comctl32.dll
#pragma comment(lib, "comctl32.lib")
// 指定加载6.x版本的comctl32.dll,而不是5.x版本(5.x版本很多功能没有)
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
                                      
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
                                      
INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
                                      
int APIENTRY wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
                     LPWSTR lpCmdLine, int nCmdShow)
{
    SetProcessDPIAware(); // 设置DPI兼容
    CoInitialize(NULL); // 初始化COM
    InitCommonControls(); // 链接comctl32.dll
    InitNetworkAddressControl(); // 加载NetworkAddress控件
    HMODULE hriched20 = LoadLibrary(L"riched20.dll"); // 加载RichEdit2.0控件
                                          
    int retval = DialogBox(NULL, (LPCTSTR)IDD_DIALOG1, NULL, DlgProc);
                                      
    FreeLibrary(hriched20); // 卸载RichEdit2.0控件
    CoUninitialize(); // 卸载COM
    return retval;
}
                                      
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_INITDIALOG:
        return TRUE;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
        case IDCANCEL:
            EndDialog(hwnd, LOWORD(wParam));
            return TRUE;
        }
        break;
    case WM_CLOSE:
        EndDialog(hwnd, 0);
        return TRUE;
    }
    return FALSE;
}</richedit.h></commctrl.h></windows.h>
[ 修改于11年0个月前 - 2015/12/26 17:59:56 ]
acmilan作者
11年0个月前IP:四川
802065
1楼
单实例对话框(最多只创建一个)数据可以保存到静态变量或全局变量中。
多实例对话框(可重复创建的对话框)数据的保存:
1.实例数据传入可以使用DialogBoxParam或CreateDialogParam,最后一个参数就是WM_INITDIALOG收到的LPARAM值。
2.实例数据的指针可以保存到DWLP_USER字段中。使用SetWindowLongPtr(hwnd, DWLP_USER, lParam);保存。
------
单实例窗口,和单实例对话框相同,数据可以保存到静态变量或全局变量中。
多实例窗口或自定义控件(可重复创建的):
1.注册类时,设置wndclass.cbWndExtra=DLGWINDOWEXTRA
2.实例数据的指针可以使用CreateWindowEx最后一个参数传入,在WM_CREATE中以((LPCREATESTRUCT)lParam)->lpCreateParams读取。
3.实例数据的指针可以保存到DWLP_USER字段中。使用SetWindowLongPtr(hwnd, DWLP_USER, lParam);保存。
------
对话框中,如果消息需要返回一个值,使用SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1234);设置返回值。
引用
评论
acmilan作者
11年0个月前IP:四川
802076
2楼
Win32对话框的28个控件比起WPF的控件数量来说还是太少了。还是WPF好用。
引用
评论
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的