windows编程笔记

1.句柄(HANDLE):每个windows资源都独有的“身份证

我们对某个窗口实现操作的话,首先要得到窗口句柄HWND。

windows程序中,有各种各样的资源,比如窗口、图标、光标等,系统创建这些资源会分配内存,并返回这些资源的标识号,这标识号就是句柄

2.消息:windows应用程序与操作系统间的“信使”

消息的表现形式--MSG结构体

typedef struct tagMSG{

  HWND hwnd;//定义消息所属的窗口

   UINT message;//指定消息的标识符  ,消息是由一个数值来表示的,不同消息对应不同数值,数值不方便记忆,将其定义为宏的形式WM_XXX ,如鼠标左键                                                                           //WM_LBUTTONDBLCLK   ,VS中鼠标选择该代码WM_XXX右键,转到定义,(F12可查看具体定义)                  

   WPARAM wParam;//指定msg的附加信息

   LPARAM  lParam;//指定msg的附加信息

   DWORD time;//指定投递到消息队列的时间

   POINT pt;//指定投递到消息队列中时鼠标的当前位置

}MSG;

窗口创建四部曲---设计,注册,创建,显示与更新。
3.设计
在windows中控制窗口的特征的结构体有两个,我们现在用更被时代喜爱的WINDCLASSEX机构体
typedef struct tagWINDCLASSEX{
 UINT cbSize;                                //表示该结构体字节数的大小,一般在主窗口函数这样写:windClass.cbSize=sizeof(WNDCLASSEX);
 UINT style;                                    //指定窗口的样式风格,取多个要用“|”来连接,eg:CS_HREDRAW等。
 WINDPROC lpfnWndProc;        //函数指针,指向窗口过程函数。
 int cbClsExtra;                              //窗口类附加内存,一般设置为零。winClass.cbClsExtra=0;
 int cbWndExtra;                            //窗口附加内存。
 HINSTANCE hInstance;             // 包含窗口过程的实例句柄。把winMain函数的第一个参数,也就是当前运行的实例句柄传给他。winClass.hInstance =hInstance;
 HICON hIcon;                                //窗口类的图标句柄,如果为NULL,则为默认图标。
 HCURSOR hCursor;                    //光标句柄
 HBRUSH hbrBackground;          //窗口类的背景画刷句柄
 LPCTSTR lpszMenuName;         //菜单资源的名字,没有菜单设置为NULL
 LPCTSTR lpszClassName;         //以一个空终止的字符串指定窗口类的名字。winClass.lpszClassName=_T("forthetream");
 HICON hIconSm;                           //右下角小图标的句柄
} WNDCLASSEX.*PWNDCLASSEX;

在WInMain函数中定义一个WINDCLASSEX
WINDCLASSEX wndClass ={0};
窗口过程函数被调用的过程:待写。

4.窗口类的注册。
在设计完跑车后,需要经国家部门有关批准才能合法生产这种跑车。在设计完窗口类后,需要调用RegisterClassEx函数对其进行注册。
RegisterClassEx(&wndClass);

5.窗口类的正式创建
Createwindow函数来创建设计好的窗口
原型声明
HWND WINAPI CreatorWindow{
_In_opt_ LPCTSTR   lpClassName,            //对应窗口类的名称就是设计类的winClass.lpszClassName=_T("forthetream")
  _In_opt_ LPCTSTR   lpWindowName,         //游戏窗口左上角标题栏的名字,如 植物大战僵尸
  _In_     DWORD     dwStyle,        //窗口样式,指定某个具体窗口的样式,WNDCLASSEX中的style成员是以后的窗口都基于这个窗口样式,
                                              //一个代表性样式WS_OVERLAPPEDWINDOW 标题栏,系统菜单,可调边框,最小化,最大化。
_In_     int       x,              //窗口的水平位置,一般我们喜欢取CW_USEDEFAULT,表示默认的位置。
 _In_     int       y,             //窗口的竖直位置,同样的喜欢取CW_USEDEFAULT,表示默认的位置。
  _In_     int       nWidth,       //指定窗口宽度
  _In_     int       nHeight,      //窗口高度
  _In_opt_ HWND      hWndParent,        //指定被创建窗口的父窗口句柄,一般设为NULL
  _In_opt_ HMENU     hMenu,              //窗口菜单资源的句柄,一般设为NULL
  _In_opt_ HINSTANCE hInstance,              //窗口所属的应用程序实例句柄,应用程序的ID,即WinMain函数的第一个参数一致,hInstance.
  _In_opt_ LPVOID    lpParam              //附加参数传入指针,大多数设为NULL。
}
如果窗口创建成功,该函数会返回一个句柄,如果失败则为NULL
在这之前,我们先定义一个窗口句柄变量,
HWND hWnd=CreateWindow(
_T("forthetream"),"致我们永不熄灭的梦想",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,600,NULL,NULL,hInstance,NULL);

6.窗口的显示与更新。
设定窗口位置的函数MoveWindow
BOOL WINAPI MoveWindow(     
  _In_ HWND hWnd,           //CreaterWindow窗口创建的窗口句柄,
  _In_ int  X,             //指定窗口左方相对于屏幕左上角的新位置
  _In_ int  Y,             //上方相对于屏幕左上角的新位置
  _In_ int  nWidth,        //窗口新宽度
  _In_ int  nHeight,       //窗口新高度
  _In_ BOOL bRepaint        //指定是否要重新画窗口,如果为FALSE的话,不会发生任何类型的重画操作。
);
下面代码就是改变一下窗口的位置
Movewindow(hWnd,200,50,800,600,ture);//窗口左上角位于屏幕坐标(200,50)处。
显示窗口
BOOL WINAPI ShowWindow( 
 _In_ HWND hWnd,            //之前窗口的句柄
 _In_ int nCmdShow          //窗口的显示状态,可以直接填nCmdShow,因为这个函数时WinMain函数内部调用的
);  
实例:ShowWindow(hWnd,nShowCmd);

更新窗口
显示窗口后,我们要更行刷新一下,好比买新房子要装修下, UpdateWindow(hWnd);

两套消息循环体系

四部曲的洗礼之后,我们要编写一个消息循环,不断的从消息列队中取出消息,并且进行响应。有俩个函数GetMessage 和PeekMessage
GetMessage
BOOL WINAPI GetMessage(
  _Out_    LPMSG lpMsg,              //它指向一个消息(MSG)机构体,从线程的消息列队中取出的消息信息保存在结构体中。
  _In_opt_ HWND  hWnd,                 //指定接受属于哪一个窗口的消息,一般设为NULL,表示接收属于调用线程的所用窗口的窗口信息。
  _In_     UINT  wMsgFilterMin,    //接受信息最小值,一般设为零就好
  _In_     UINT  wMsgFilterMax     //接受信息最大值,设置为零的话表示接收所用消息,来者不拒
);
以GetMessage消息循环来写一个固定的消息循环:
MSG msg={0};
while(GetMessage(&msg,NULL,0,0)) //不断从消息队列中取出消息
{
TranslateMessage(&msg); //将虚拟键消息转换为字符消息
DispatchMessage(&msg); //分发一个消息给窗口程序
}

PeekMessage

BOOL WINAPI PeekMessage(
  _Out_    LPMSG lpMsg,          //和上述一样
  _In_opt_ HWND  hWnd,
  _In_     UINT  wMsgFilterMin,
  _In_     UINT  wMsgFilterMax,
  _In_     UINT  wRemoveMsg    //指定于消息的获取方式,一般在PM NOREMOVE 和PM REMOVE中取值,如果为前者,PeekMessage函数取出某条消息后,消息将不会从消息队列中被移除(就像这条消息被偷看了一样);如果为后者,这条消息将从消息队列中移除(就像消息被拿走了一样)
);
GetMessage与PeekMessage的不同点:
·PeekMessage 有点像乞丐,有你就施舍点,没有也不强求,使其处理消息很顺畅,符合游戏运行要求。
·GetMessage 像强盗打劫,有你得给,没有我就等你有,它处理消息时程序在没有消息的时候处于休眠状态,不符合游戏运行要求。

windows程序的中枢神经--窗口过程函数

主要用于处理发送给窗口的消息,
LRESULT CALLBACK WindowProc(   //他的名字在实际编写程序过程中可以随便取的,不一定叫WindowProc。注意:系统通过窗口过程函数的地址来调用,而不是名字。
  _In_ HWND   hwnd,         //要处理窗口的句柄
  _In_ UINT   uMsg,         //待处理消息的ID,即消息的类型。
  _In_ WPARAM wParam,         //附加信息
  _In_ LPARAM lParam          //附加信息
);   

做好善后--窗口类的注销
用到的是UnregisterClass,与之前的RegisterClassEx对应,注意前者没有Ex,
UnregisterClass(类名称,实例句柄);
UnregisterClass(L"gofortream",winClass.hInstance);


代码实例

#include <Windows.h>

//宏定义部分
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_TITLE L"为梦想而战"

//全局函数声明
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam);//窗口过程函数

//winMain 函数 我们的程序从这里开始。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    //一。设计一个完整的窗口类
    WNDCLASSEX wndClass = { 0 };
    wndClass.cbSize = sizeof(WNDCLASSEX);
    wndClass.style = CS_HREDRAW | CS_VREDRAW;
    wndClass.lpfnWndProc = WndProc;
    wndClass.cbClsExtra = 0;
    wndClass.cbWndExtra = 0;
    wndClass.hInstance = hInstance;
    wndClass.hIcon = (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);
    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
    wndClass.lpszMenuName = NULL;
    wndClass.lpszClassName =L"goforgream";

    //二。注册窗口类
    if (!RegisterClassEx(&wndClass))
        return -1;

    //三。创建窗口
    HWND hwnd = CreateWindow(L"goforgream", WINDOW_TITLE,
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
        WINDOW_HEIGHT, NULL,NULL, hInstance, NULL);

    //四。窗口的移动、显示与更新
    MoveWindow(hwnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);
    ShowWindow(hwnd, nShowCmd);

    //五。消息循环
    MSG msg = { 0 };
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    //六。窗口类的注销。
    UnregisterClass(L"goforgream", wndClass.hInstance);
    return 0;
}

    //窗口过程函数,消息处理。
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_PAINT:
            ValidateRect(hwnd, NULL);
            break;
        case WM_KEYDOWN:
            if (wParam == VK_ESCAPE)
                DestroyWindow(hwnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    }

 
图片放到该项目的debug文件下。


   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值