C++自制简易连点器番外篇附加一个坑

1、开场白

来了,来了,番外篇来了。。。。。。。。。

1.5、回忆杀

有些时候吧,真的想给自己一个大逼斗。

上上篇(文章链接)最后说要明年才能写完,但其实当时基本上已经做完了,但是就在我测试的时候发现了一个逆天Bug,点击按键切换后无法生效,这就意味着核心功能直接丧失了,我调试了好就,微软官方的资料翻了又翻,就是找不到问题在哪儿,然后我就被这个Bug卡了一个多月。。。。。。直到昨天晚上,我在看代码时突然就找到问题了。。。。。。

在回调函数WindowProc中,有一个整形变量(局部)ClickKey,用于记录当前点击按键,它的初始值是0,表示鼠标左键。我添加了一个组合框控件,其中有三个选项,默认选中第一项,也就是鼠标左键。我对CBN_SELCHANGE(组合框当前选中项发生改变)消息进行操作,每收到一次就获取当前选中项的索引(恰好对应0,1,2)并赋值给ClickKey,最后在计时器消息中对每一个值做出不同的操作。可以说明的是,上述操作中没有任何逻辑、顺序错误,错就错在ClickKey是一个局部变量。。。。

1.9、坑

在回调函数中总有如下代码结构:

switch(uMsg)
{
case WM_CREATE:
    break;
case WM_PAINT:
    break;
case WM_COMMAND:
    break;
case WM_HOTKEY:
    break;
case WM_TIMER:
    break;
     ...
}

在这看似简单的代码中有一个惊天大坑:假设在函数内部、switch外部定义一个局部变量并赋值,然后在WM_COMMAND消息中对这个值做出改变,最后在WM_TIMER中使用该变量,那么这个变量的值将不会发生任何改变,依旧是他的初始值。为什么?因为当WM_COMMAND分支结束后会立刻销毁变量的值,也就意味着它会被初始化。。。。。。要解决它有两种方法:一是设为全局变量,二是设为静态变量,这两种变量的生命周期都要比局部变量长。

好好好,说到底,我调试来调试去,最后一切的根源就是少写了六个英文字母。。。。。。

2、正片

制作第一步--创建窗口

直接给出熟悉的代码

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //创建窗口类
	WNDCLASSEX wndclass = { 0 };
	HWND hwnd;
	MSG msg;
	TCHAR lpszClassName[]  = { TEXT("MouseClickerWin32") };
	TCHAR lpszAppName[]    = { TEXT("鼠标连点器") };
	wndclass.cbSize        = sizeof(WNDCLASSEX);
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.style         = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc   = WindowProc;
	wndclass.hInstance     = hInstance;
	wndclass.hIcon         = LoadIcon(hInstance, IDI_APPLICATION);
	wndclass.hIconSm       = NULL;
	wndclass.hCursor       = LoadCursor(hInstance, IDC_ARROW);
	wndclass.hbrBackground = CreateSolidBrush(0xFFFFFF);
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = lpszClassName;

    //注册窗口类
	RegisterClassEx(&wndclass);

    //创建窗口
	hwnd = CreateWindowEx(WS_EX_TOPMOST, lpszClassName, lpszAppName, 
            WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX,
			CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HIGHT, NULL, NULL, hInstance, NULL);

    //显示窗口
	ShowWindow(hwnd, SW_SHOW);

    //更新窗口
	UpdateWindow(hwnd);

    //消息循环
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

    //WinMain函数返回值
	return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_DESTROY:            //窗口销毁消息处理
        PostQuitMessage(0);     //销毁窗口
        break;
    }
}

制作第二步--基本准备

首先为了控制代码量,这里要批量创建控件,因此需要定义一个有关的结构体,并创建结构数组以保存每个控件的信息

这里创建一个头文件来定义结构体以及存放控件ID

//fResource.h头文件
//////////////////////////////////////////////////////////
#pragma once
#ifndef FRESOURCE_H_
#define FRESOURCE_H_
#define WIDTH               255        //窗口宽度
#define HIGHT               150        //窗口高度
#define IDC_BTN_MODIFY      1001       //修改按钮
#define IDC_BTN_OK          1002       //确定按钮
#define IDC_BTN_CANCLE      1003       //取消按钮
#define IDC_CBX_CLICKKEY    1004       //点击按键组合框
#define IDC_EDIT_INR        1005       //点击间隔编辑框
#define IDT_TIMER           1006       //计时器(控制点击)
#define IDT_TIMER_EDITSCAN  1007       //计时器(检测编辑控件中是否有内容)
#define HKEY_ALT            0x1011     //热键

typedef struct ControllersInfo
{
	int x;
	int y;
	int nWidth;
	int nHight;
	LPCTSTR lpszClaaName;
	LPCTSTR lpszWindowName;
	LONG wndStyle;
	int nID;
}CONTROLLERSINFOSTRUCT;
#endif // !FRESOURCE_H_

接着在MouseClicker.cpp中声明结构体变量并初始化

//MouseClicker.cpp
////////////
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值