WTL基础入门

本文介绍了Windows Template Library (WTL)的基础入门知识,包括如何在Visual Studio 2019中配置WTL环境,创建第一个显示"Hello World"的窗口,并解析关键代码段的功能。此外,还提到了WTL提供的MTPad案例,展示了一个简易记事本应用的实现,帮助读者更深入理解WTL的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

WTL基础入门

基于VS2019的WTL环境搭建

WTL,即Windows Template Library,提供了一套用于Windows的组件,由于体积很小,而且生成的exe也很小,所以做一些测试软件就十分经济。

首先,下载并解压,将解压后的include文件夹的绝对路径添加到工程的VC++目录中。

具体操作为,右键项目名称->属性(快捷键Shift+F4),选择VC++目录,将include的绝对路径添加到包含目录中。

需要注意一点,由于我们的程序入口不再是main函数,所以在运行前需要检查是否已经设置。其入口仍然在项目设置中,位于链接器->所有选项->子系统,选择窗口 (/SUBSYSTEM:WINDOWS)

第一个窗口

include文件夹中是WTL的头文件,大致如下

文件名说明
atlapp.h信息循环、接口等
atlcrack.h消息宏
atlctrls.h标准控件库类
atlctrlw.h命令栏类
atlctrlx.h位图、按钮、框选列表等控件
atlddx.h用于对话框、窗口的数据交互
atldlgs.h对话框类、属性表以及页面类
atlframe.h窗口类
atlgdi.hDC和GDI类
atlmisc.h一些C语言的内容
atlprint.h打印和打印预览
atlres.h标准资源ID
atlscrl.h滚动条窗口
atlsplit.h分割窗口
atluser.h菜单类

由于我们只是希望新建一个窗口,所以不需要这么多的头文件,新建一个stdafx.h,暂时include下列.h

//stdafx.h
#pragma once

#include <atlstr.h>
#include <atlapp.h>
extern CAppModule _Module;
#define _WTL_NO_CSTRING
#include <atlmisc.h>
#include <atlcrack.h>
#include <atlframe.h>

然后在cpp文件中写入代码

#include "stdafx.h"

CAppModule _Module;

class myWindow :public CWindowImpl<myWindow, CWindow> {
    BEGIN_MSG_MAP(myWindow)
        END_MSG_MAP()
};

//入口函数
int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow) {
    _Module.Init(NULL, hInstance);  //初始化模型
    MSG msg;
    
    myWindow Window;        //声明一个窗口
    //创建一个矩形
    CRect rc = CRect(POINT{ 100, 100 }, //左上角点的坐标
                    POINT{ 900, 500 }); //右下角点的坐标
    
    //创建窗口
    Window.Create(NULL, rc, "Hello world", WS_VISIBLE);

    while (GetMessage(&msg, NULL, 0,0)>0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    _Module.Term();
    return msg.wParam;
}

运行之后得到下图

在这里插入图片描述

可见我们真的创建了一个窗口,而且这个窗口除了Hello World之外一无所有。

部分代码的详解

其中大致有3个地方需要详细解释一下。

  1. BEGIN_MSG_MAP(myWindow) END_MSG_MAP()

这段诡异的没有;的代码不出意外是被define了,如果有兴趣可以F12查看一下源代码。下面是经过转换之后的写法

public:
BOOL ProcessWindowMessage(_In_ HWND hWnd, _In_ UINT uMsg,
    _In_ WPARAM wParam, _In_ LPARAM lParam,
    _Inout_ LRESULT& lResult, _In_ DWORD dwMsgMapID = 0)
{
	BOOL bHandled = TRUE;
	(hWnd);     //窗口句柄
	(uMsg);     //消息代码
	(wParam);   //其他消息数据
	(lParam);   //其他消息数据
	(lResult);  //程序返回给 Windows 的整数值
	(bHandled);
	switch(dwMsgMapID)
	{
	case 0:
        break;
	default:
		ATLTRACE(static_cast<int>(ATL::atlTraceWindowing), 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID);
        ATLASSERT(FALSE);
		break;
	}
	return FALSE;
}

即创建了一个公开的布尔型函数,用以写入各种窗口句柄和消息数据。

  1. Window.Create()

其定义为

HWND Create(
	_In_opt_ HWND hWndParent,   //父句柄
	_In_ _U_RECT rect = NULL,   //位置大小
	_In_opt_z_ LPCTSTR szWindowName = NULL, //窗口名
	_In_ DWORD dwStyle = 0,     //窗口风格
	_In_ DWORD dwExStyle = 0,   //扩展风格
	_In_ _U_MENUorID MenuOrID = 0U,     //资源IO
	_In_opt_ LPVOID lpCreateParam = NULL)   //貌似没什么卵用

其中,窗口风格我们填了WS_VISIBLE,表示窗口是可见的。这一项可以通过|运算来构造更加丰富的窗口类型。一个简单的例子就是,我们最起码想要创建一个带有-口×的窗口。那么就可以将这一项改为

WS_VISIBLE|WS_SYSMENU|WS_MINIMIZEBOX |WS_MAXIMIZEBOX

  1. while()循环

这个循环就是程序的主循环。

其中,GetMessage顾名思义,就是获取信息,如果传入了推出的信息,则返回值为-1,从而退出循环。

TranslateMessage()用于处理信息;DispatchMessage(&msg);用于响应窗口操作。

WTL自带的MTPad案例

在WTL的解压文件里,除了include文件夹之外,还有一个Sample文件夹,提供了一些基本案例。

其中MTPad编译运行之后如图所示

在这里插入图片描述

是个记事本文件,尽管看上去很有年代感,但这完全是res文件夹下图片的锅,只要把图片换一下,就完全看不出年代感了。

debug文件夹下可发现其exe文件为1.2M。其源代码包括一个mtpad.cpp,外加7个头文件,总计1200多行代码。

首先来看一下mtpad.cpp

#include "stdatl.h"

#include <atlframe.h>
#include <atlctrls.h>
#include <atlctrlx.h>
#include <atldlgs.h>
#include <atlmisc.h>
#include <atlctrlw.h>
#include <atlprint.h>
#include <atlfind.h>
#include "finddlg.h"

#include "resource.h"

// Globals
#define WM_UPDATEROWCOL		(WM_USER + 1000)

LPCTSTR lpcstrMTPadRegKey = _T("Software\\Microsoft\\WTL Samples\\MTPad");


LPCTSTR lpcstrFilter = 
	_T("All Files (*.*)\0*.*\0")
	_T("Text Files (*.txt)\0*.txt\0")
	_T("C++ Files (*.cpp)\0*.cpp\0")
	_T("Include Files (*.h)\0*.h\0")
	_T("C Files (*.c)\0*.c\0")
	_T("Inline Files (*.inl)\0*.inl\0")
	_T("Ini Files (*.ini)\0*.ini\0")
	_T("Batch Files (*.bat)\0*.bat\0")
	_T("");

#include "view.h"
#include "aboutdlg.h"
#include "mainfrm.h"

#include "mtpad.h"

CAppModule _Module;

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int nCmdShow)
{
	_Module.Init(NULL, hInstance);

    //加载文本编辑控件
	HINSTANCE hInstRich = ::LoadLibrary(CRichEditCtrl::GetLibraryName());

	CThreadManager mgr;
	int nRet = mgr.Run(lpCmdLine, nCmdShow);

	::FreeLibrary(hInstRich);//释放内存
	_Module.Term();

	return nRet;
}

这段代码有3点值得一提:

  1. _T(x)L##x通过define得到,后者表示在表达式x前面加一个L。而L开头的字符串表示Unicode编码。
  2. ::LoadLibrary,一般双冒号用于索引,比如A::B表示A中的成员B,而以::开头,表示该变量是全局变量。
  3. CThreadManagermtpad.h中封装的类,顾名思义,用于线程管理。在这个类中,定义了Run函数,Run函数中写入了一个while循环,起到窗口待命的作用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微小冷

请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值