流程

1 建立并注册windows类

2 使用windows类创建窗口

3 实现事件处理,主循环


PeekMessage与GetMessage的对比

相同点:

PeekMessage函数与GetMessage函数都用于查看应用程序消息队列,有消息时将队列中的消息派发出去。

不同点:

无论应用程序消息队列是否有消息,PeekMessage函数都立即返回,程序得以继续执行后面的语句(无消息则执行其它指令,有消息时一般要将消息派发出去,再执行其它指令)。

GetMessage函数只有在消息对立中有消息时返回,队列中无消息就会一直等,直至下一个消息出现时才返回。在等的这段时间,应用程序不能执行任何指令。


游戏时一般使用PeekMessage不阻塞,主循环里除了事件外还要处理绘制逻辑等。

TranslateMessage

将虚拟键消息转换为字符消息。字符消息被送到调用线程的消息队列中,在下一次线程调用函数GetMessage或PeekMessage时被读出将虚拟键

消息转换为字符消息。字符消息被送到调用线程的消息队列中,在下一次线程调用函数GetMessage或PeekMessage时被读出


DispatchMessage

该函数调度一个消息给窗口程序。通常调度从GetMessage取得的消息。消息被调度到的窗口程序即是MainProc()函数



4 实现事件回调处理WinProc

代码

实现上面流程的全部代码,其中全屏相关部分可以去掉(游戏往往才会用到全屏,下面代码主要用来展示win程序创建流程),如果是使用opengl等做游戏,与下面代码不同的地方主要是主循环与绘制方式不同

#include "stdafx.h"
#include "Win_Base.h" HINSTANCE hInst; //当前应用的实例句柄
HWND hWnd; //窗口句柄 bool exiting = false; //循环开启标志
bool fullscreen=FALSE; //全屏标志
long windowWidth = 800; //默认窗口宽
long windowHeight = 600;//默认窗口高
long windowBits = 32; //每像素所选的色彩深度 ATOM RegisterWinClass(HINSTANCE hInstance);
BOOL CreateWin(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg; //step1 创建并,注册windows class
RegisterWinClass(hInstance); //step2 创建(全屏或者非全屏)窗口
if (!CreateWin(hInstance, nCmdShow))
{
return FALSE;
} //step3 主循环事件处理
while (!exiting)
{
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage (&msg, NULL, 0, 0))
{
exiting = true;
break;
} TranslateMessage (&msg);
DispatchMessage (&msg);
}
} if (fullscreen)
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
} return (int) msg.wParam;
} //创建并,注册windows class
ATOM RegisterWinClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc; //时间回调函数指针
wcex.cbClsExtra = 0; //
wcex.cbWndExtra = 0; //
wcex.hInstance = hInstance; //实例
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "BaseClass";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
} //创建(全屏或者非全屏)窗口
BOOL CreateWin(HINSTANCE hInstance, int nCmdShow)
{
//设置全屏,创建窗口都要用到
DWORD dwExStyle; //扩展窗口风格
DWORD dwStyle; //窗口风格 RECT windowRect; //取得矩形的左上角和右下角的坐标值
windowRect.left=(long)0;
windowRect.right=(long)windowWidth;
windowRect.top=(long)0;
windowRect.bottom=(long)windowHeight; hInst = hInstance; //使用全局变量存储应用实例(win32工程默认在这个位置赋值) //设置全屏状态开始-------------------------------------------------------------
if (fullscreen)
{
DEVMODE dmScreenSettings; //设备模式
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); //情况内存
dmScreenSettings.dmSize = sizeof(dmScreenSettings); //DEVMODE结构size
dmScreenSettings.dmPelsWidth = windowWidth; //屏幕宽
dmScreenSettings.dmPelsHeight = windowHeight; //屏幕高
dmScreenSettings.dmBitsPerPel = windowBits; //每像素所选的色彩深度
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
//尝试设置显示模式并返回结果。注: CDS_FULLSCREEN 移去了状态条。
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
fullscreen = FALSE;
}
} //由于全屏模式可能失败,用户可能决定在窗口下运行,我们需要在设置屏幕/窗口之前,再次检查fullscreen的值是TRUE或FALSE。
//如果我们仍处于全屏模式,设置扩展窗体风格为WS_EX_APPWINDOW,这将强制我们的窗体可见时处于最前面。再将窗体的风格设为WS_POPUP。这个类型的窗体没有边框,使我们的全屏模式得以完美显示。
//最后我们禁用鼠标指针。当您的程序不是交互式的时候,在全屏模式下禁用鼠标指针通常是个好主意。
//如果我们使用窗口而不是全屏模式,我们在扩展窗体风格中增加了 WS_EX_WINDOWEDGE,增强窗体的3D感观。
//窗体风格改用 WS_OVERLAPPEDWINDOW,创建一个带标题栏、可变大小的边框、菜单和最大化/最小化按钮的窗体。
if (fullscreen)
{
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_POPUP;
ShowCursor(FALSE);
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
} AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);//调整窗口达到真正要求的大小 //设置全屏状态结束------------------------------------------------------------- //创建窗口开始---------------------------------------------------------------------
hWnd = CreateWindowEx(
NULL, // 扩展窗体风格
"BaseClass", // 类名字
"Title", // 窗口标题
dwStyle | // 选择的窗体属性
WS_CLIPCHILDREN | // 必须的窗体风格属性
WS_CLIPSIBLINGS, // 必须的窗体风格属性
0, 0, // 窗口位置
windowRect.right - windowRect.left, // 计算调整好的窗口宽度
windowRect.bottom - windowRect.top, // 计算调整好的窗口高度
NULL, // 无父窗口
NULL, // 无菜单
hInstance, // 实例
NULL); // 不向WM_CREATE传递任何参数 if (!hWnd)
{
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
//创建窗口结束--------------------------------------------------------------------- ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd); return TRUE;
} LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc; switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//绘制代码
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

WINDOWS编程基础-最简单的windows程序的更多相关文章

  1. Windows socket之最简单的socket程序

    原文:Windows socket之最简单的socket程序 最简单的服务器的socket程序流程如下(面向连接的TCP连接 ): 1. WSAStartup(); 初始化网络库的使用. 2. soc ...

  2. Windows编程基础

    主要内容:介绍Windows编程的一些基础概念 1.窗口的概念 <1>一个应用程序的窗口通常包括控制菜单框.下拉菜单. 工作区以及最大化按钮.最小化按钮, 还有垂直滚动条.水平滚动条 &l ...

  3. Android 网络编程基础之简单聊天程序

    前一篇讲了Android的网络编程基础,今天写了一个简单的聊天程序分享一下 首先是服务端代码: package com.jiao.socketdemo; import java.io.Buffered ...

  4. Windows编程中的若干难点 - Windows程序设计(SDK)007

    Windows编程中的若干难点 让编程改变世界 Change the world by program 一个窗口的生与死 我记得有童鞋会问:如果我的程序需要在关闭前让用户判断是否确定要关闭窗口,我应该 ...

  5. 第一章 Windows编程基础(1~4课)

    第一课:从main到WinMain 第二课:窗口和消息 第三课:MFC编程 第四课:MFC应用程序框架 概括: Win32的两种编程框架:SDK方式.MFC方式 1. SDK方式:使用WinMain入 ...

  6. Windows 编程基础

    1 Windows应用程序的分类 1.1 控制台程序 DOS程序,本身没有窗口,通过WINDOWS下的DOS窗口执行. 1.2 窗口程序 拥有自己的窗口,通过窗口可以和用户进行交互.(比如:记事本,画 ...

  7. 《Windows编程循序渐进》——建立MFC应用程序

    如何建立MFC应用程序 打开VS2013:

  8. MFC入门教程01 Windows编程基础

  9. C#编程基础(简单概述与理解)

    1.C#变量和数据输入 C#常用到的几个数据类型: 整型:int 说明:32位有符号整数 范围:-2³¹~2³¹-1 浮点型:double 说明:64位双精度浮点数 范围:±5.0×10-­﹣³²~± ...

随机推荐

  1. CI框架常识

    1.有两种方法来加载自定义配置文件(如enums.php): <?php if (! defined('BASEPATH')) exit('No direct script access all ...

  2. 深入理解Java:注解(Annotation)自己定义注解入门

    深入理解Java:注解(Annotation)自己定义注解入门 要深入学习注解.我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前.我们就必须要了解Java为我们提供的元注解和相关定义注解的 ...

  3. 2-3-4树的java实现

    一.什么是2-3-4树 2-3-4树和红黑树一样,也是平衡树.只不过不是二叉树,它的子节点数目可以达到4个. 每个节点存储的数据项可以达到3个.名字中的2,3,4是指节点可能包含的子节点数目.具体而言 ...

  4. 九度OJ 1086:最小花费 (DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3960 解决:819 题目描述: 在某条线路上有N个火车站,有三种距离的路程,L1,L2,L3,对应的价格为C1,C2,C3.其对应关系如下 ...

  5. Gym - 100187A A - Potion of Immortality —— 贪心

    题目链接:http://codeforces.com/gym/100187/problem/A 题解: 光题意就想了很久:在最坏情况下的最小兔子数.其实就是至少用几只兔子就一定能找出仙药(答案存在的话 ...

  6. 关于Linux启动文件rc.local的解惑

    背景 首先,rc.local是Linux启动程序在login程序前执行的最后一个脚本,有的服务器中在rc.local中可能会有一句touch /var/lock/subsys/local,这是干什么的 ...

  7. git rev-list 和 git rev-parse

    git-rev-list - Lists commit objects in reverse chronological order https://git-scm.com/docs/git-rev- ...

  8. ansible安全优化建议

    摘自 ansible自动化配置书籍,特此感谢 针对非授权连接和截取通信息等共计行为,我们总结了9条方法: 使用安全加密的通信方式 禁止root用户远程登录并充分利用sudo 移除非必须的软件,只开放需 ...

  9. struts2 小例子(教训篇)

    学了一阵子的struts2了,到了最后,想自己写个小程序,发现最简单的配置文件都 竟然能弄错,是我这几天睡眠不足么.怎么可能,爱好这门的,怎么会这样.这样真的很伤心啊.小小心灵受不了这种打击啊.... ...

  10. 在KitKat(Android 4.4.2) 推送网址给手机

    弱者才会回避问题. 最近想把网址推送给手机实现后台下载,打算故技重施,用短信传送然后中断广播的方法实现隐蔽传送.试了半天发现怎么现在拦不住短信了.查了一下才发现原来Android4.4增加了一个安全机 ...