最小的一个窗口

#include "windows.h"

HINSTANCE g_hInstance;

LRESULT CALLBACK MainWndProc(_In_ HWND hWnd,_In_ UINT uMsg,_In_ WPARAM wParam,_In_ LPARAM lParam)
{
    //每一个发给这个窗体的消息,通过不同的uMsg消息来做不同的动作,wParam和lParam保存的是这个消息的具体参数

    switch(uMsg)
    {
    case WM_CREATE:
    //这里可以添加创建时的界面选项,不要做耗时操作。
        break;
    case WM_CLOSE:
        break;
    case  WM_COMMAND:
        break;
    case WM_LBUTTONDOWN:
        MessageBox(0,"单击后的效果","Title",MB_OK);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);//按关闭按钮后,向GetMessage发送一个关闭的消息,然他退出循环,结束进程
        break;
    default:
        return DefWindowProc(hWnd,uMsg,wParam,lParam);
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
    g_hInstance = hInstance;
    WNDCLASS MyWcs= {};
    MyWcs.lpszClassName = "LpszClassName";
    MyWcs.lpfnWndProc = MainWndProc;////这里定义消息处理函数 很重要
    MyWcs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH+2);       
    MyWcs.style = CS_HREDRAW | CS_VREDRAW;

    RegisterClass(&MyWcs);//注册为窗口类 

    HWND hWnd = CreateWindow(
        "LpszClassName",           //   这个名字要和上面定义的lpszClassName名字一致
        "Sample_Tile",            // title-bar string 
        WS_OVERLAPPEDWINDOW, // top-level window 
        CW_USEDEFAULT,       // default horizontal position 
        CW_USEDEFAULT,       // default vertical position 
        290,       // default width 
        500,       // default height 
        (HWND) NULL,         // no owner window 
        (HMENU) NULL,        // use class menu 
        hInstance,           // handle to application instance 
        (LPVOID) NULL);      // no window-creation data 
    ShowWindow(hWnd,SW_SHOW);//展示窗口,不不展示的话你看不到图案,程序会在后台运行 

    MSG msg = {};
    while (GetMessage(&msg,NULL,NULL,NULL))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

在这里插入图片描述

以上就是一个最基本窗体了,最重要的是以下几步

1.定义窗口类:定义了这个类的回调函数,也就是说使用这个类创建的窗体的消息由这里设置的函数处理。这个类控制着这个窗口的样式,比如颜色,背景,风格等等,这个窗口类可以多次使用。

2.创建窗口:现在你就可以使用上面定义好的类,来创建一个窗口,可以控制窗口出现的位置,大小和一些其他选项

3.创建循环接收消息:因为Windows是消息机制,循环接收发给控件的消息,我们就可以处理这些消息,这些消息比如鼠标点击了窗体,键盘按下了某个键,或者点击了那个按钮,这些都是不同的消息类型

下面是使用win32控制计算机的模拟按键在这里插入图片描述
这里只贴核心代码,其他都一样



LRESULT CALLBACK OnWndCommand(_In_  HWND hwnd,_In_  UINT uMsg, _In_  WPARAM wParam,_In_  LPARAM lParam)
{
    switch (HIWORD(wParam))// wParam高2位保存的是通知码,低2位保存的是控件ID
    {
    case BN_CLICKED:
        {
            switch (LOWORD(wParam))
            {
            case 0x1000:
            case 0x1001:
            case 0x1002:
                {
                    HWND hCalc = FindWindowA(NULL,"计算器");
                    if(!hCalc)
                    {
                        WinExec("calc.exe",SW_SHOW);
                        hCalc = FindWindowA(NULL,"计算器");
                    }
                    SendMessage(hCalc,WM_COMMAND,wParam-0xF7D,0);
                    return true;
                }
            }
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

消息循环中这样写


    case WM_COMMAND:
        return OnWndCommand(hWnd, uMsg, wParam, lParam);

按钮事件是WM_COMMAND来处理
https://docs.microsoft.com/en-us/windows/win32/menurc/wm-command
wParam高2位保存的是通知码,低2位保存的是控件ID

每个按钮能处理详细信息,注意看Notification(通知码类型)
https://docs.microsoft.com/en-us/windows/win32/controls/individual-control-info

根据wParam的高两位看是否是控件信息,再看wParam的低两位,代表是谁发出的这个消息。

接着我们就可以处理他了

处理的时候我FindWindowA查看有没有计算器处于打开状态,没有就开一个
最重要的一步是模拟给他发消息,就像自己给自己发一样
SendMessage(hCalc,WM_COMMAND,83,0);
SendMessage MSDN https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
在这里插入图片描述
上面这句理解为 我给hCalc 这个程序的控件ID为83的控件发送了一个WM_COMMAND消息

最后依次找到找到他们的控件ID,就能完全模拟计算器发包了



编程  

Win32 回调函数

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!