zoukankan      html  css  js  c++  java
  • WINDOWS编程基础-最简单的windows程序

    流程

    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;
    }


  • 相关阅读:
    php中global和$GLOBALS[]的分析之一
    javascript 标签 src 链接动态文件。
    Allegro基本操作——PCB布线
    AMD单桥主板上电时序的详细解释
    AMD单双桥时序简叙
    AMD移动FP5平台时序解释
    orcad元件属性批量修改(通过excel表格)
    加减乘除基本函数
    1.excel如何让一列的数都乘以固定值
    ORCAD元件属性白色区域和黄色区域的理解
  • 原文地址:https://www.cnblogs.com/nafio/p/9137614.html
Copyright © 2011-2022 走看看