3.windows图形界面

本文概述了GUI应用程序中的窗口概念,包括窗口客户区和窗口函数的重要性。详细介绍了WinMain作为GUI应用的入口函数,以及如何使用MessageBox进行基本交互。后续内容探讨了消息驱动机制,如鼠标和键盘事件处理,以及创建、显示和消息循环的基本步骤。
摘要由CSDN通过智能技术生成
  • 了解窗口
    每个GUI应用程序至少要创建一个窗口,称为主窗口。每个窗口都在显示输出和从用户取得输入方面起着一定的作用。
    窗口客户区是应用程序显示输出的部分。应用程序必须提供一个称为窗口函数的回调函数来处理窗口的输入,向客户区显示输出。
    在这里插入图片描述
  • 第一个窗口程序
int APIENTRY WinMain(
	HINSTANCE hInstance,   //本模块的实例句柄
	HINSTANCE hPrevInstance, //win16留下的产物,现在已经不用了
	LPSTR lpCmdLine,  //命令行参数
	int nCmdShow    //主窗口初始化时的显示方式
)
GUI应用程序的入口函数是WinMain,这是一个自定义的回调函数。
APIENTRY的宏定义是__stdcall
hInstance = (HINSTANCE)GetModuleHandle(NULL); //取得应用程序的实例句柄(即模块句柄)
参数为NULL时,返回可执行文件所在模块的模块句柄,而不管是在哪个模块中做调用的。

int MessageBox(
	HWND hWnd,  //一个窗口句柄,它指定哪一个窗口将拥有要创建的消息框
	LPCTSTR lpText, //将要显示的消息
	LPCTSTR lpCaption, //对话框标题
	UINT uType  //指定对话框的内容和行为
);
返回值:
IDOK、IDYES、IDNO、IDCANCEL、IDABORT、IDRETRY、IDIGNORE等
  • MessageBox中的uType参数
    在这里插入图片描述

  • 示例:简单的win32

// 04Win32AppDemo.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	// 弹出一个对话框
	MessageBox(NULL,"Hello,Win32 Application","04Win32AppDemo",MB_OK);
    MessageBox(NULL,"Hello,Win32 Application","04Win32AppDemo",MB_YESNOCANCEL|MB_ICONQUESTION|MB_DEFBUTTON3)
	return 0;
}


在这里插入图片描述
在这里插入图片描述

  • windows消息驱动
    鼠标或键盘在桌面操作时,windows会源源不段地向程序发送消息,操作这个过程的函数为窗口函数。原型如下:
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
CALLBACK 宏定义是__stdcall
uMsg:消息ID号,诸如MessageBox中的IDYES等等
wParam和lParam是消息ID的附加参数
  • 示例:收到WM_CLOSE消息关闭窗口
// 04TellToClose.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"


int main(int argc, char* argv[])
{
	HWND hWnd = FindWindow(NULL,"无标题 - 记事本");
	if(hWnd != NULL)
	{
		//向目标窗口发送WM_CLOSE消息
		SendMessage(hWnd,WM_CLOSE,0,0);
	}



	return 0;
}

桌面显示一个窗口的具体步骤:

  1. 注册窗口类(RegisterClassEx)
  2. 创建窗口 (CreateWindowEx)
  3. 在桌面显示窗口 (ShowWindow)
  4. 更新窗口客户区(UpdateWindow)
  5. 进入无限的消息循环处理
    • 获取消息GetMessage
    • DispatchMessage
    • 消息处理MainWndProc函数

示例:最简单的windows程序

// 04FirstWindow.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"

LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	char szClassName[] = "MainClass";
	WNDCLASSEX wndclass;

	//用于描述主窗口的参数填充WNDCLASSEX结构
	wndclass.cbSize = sizeof(wndclass);  //结构的大小
	wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
	wndclass.lpfnWndProc = MainWndProc;   //窗口函数指针
	wndclass.cbClsExtra = 0;              //没有额外的类内存
	wndclass.cbWndExtra = 0;             //没有额外的窗口内存
	wndclass.hInstance = hInstance;      //实例句柄
	wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);   //使用预定义图标
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);   //使用预定义光标
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
	wndclass.lpszMenuName = NULL; //不指定菜单
	wndclass.lpszClassName = szClassName;  //窗口类的名称
	wndclass.hIconSm = NULL;    //没有类的小图标

	//注册这个窗口类
	RegisterClassEx(&wndclass);
  
	//创建主窗口
	HWND hwnd = CreateWindowEx(
		0,                  //dwExSytle,扩展
		szClassName,        //lpClassName,窗口类名
		"My first Window!",    //lpWindowName,标题
		WS_OVERLAPPEDWINDOW,  //dwStyle,窗口风格
		CW_USEDEFAULT,    //X,初始化X坐标
		CW_USEDEFAULT,    //y,初始化Y坐标
		CW_USEDEFAULT,   //nWidth,宽度
		CW_USEDEFAULT,    //nHeight,高度
		NULL,          //hWindParent 父窗口句柄
		NULL,           //hMenu 菜单句柄
		hInstance,         //hInstance,程序实例句柄
        NULL	          //lpParam,用户数据	
		);

	if(hwnd == NULL)
	{
		MessageBox(NULL,"创建窗口出错!","error",MB_OK);
		return -1;
	}

    //显示窗口,刷新窗口客户区
	ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);


	//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
	MSG msg;

	while(GetMessage(&msg,NULL,0,0))
	{
		//转化为键盘消息
		TranslateMessage(&msg);
		//将消息发送到相应的窗口函数
		DispatchMessage(&msg);
		
	}

     //当GetMessage返回FALSE时程序结束
	return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	char szText[] = "最简单的窗口程序";
	switch(message)
	{
	case WM_PAINT: //窗口客户区需要重画
		{
		
			HDC hdc;
			PAINTSTRUCT ps;

			//使无效的客户区变的有效,并取得设备环境句柄
			hdc = BeginPaint(hwnd,&ps);

			//显示文字
			TextOut(hdc,10,10,szText,strlen(szText));
			EndPaint(hwnd,&ps);
			return 0;
		}
	case WM_DESTROY:  //正在销毁窗口
		//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
		PostQuitMessage(0);
		return 0;

		
	}
  //我们不处理的消息交给系统做默认处理
	return DefWindowProc(hwnd,message,wParam,lParam);

}

在这里插入图片描述

  • 使用资源
    资源是一些二进制数据,它能够添加到基于窗口的应用程序的可执行文件中。资源的源文件是以.rc为扩展名的脚本文件。
    在原来的工程下新建一个资源脚本,命令为resource
    程序左侧会生成一个resource.rc文件和resource.h文件(隐藏,得去工程目录下查找)

IDI_ICON1和IDR_TYPER可以自定义,且在函数中会使用到
在这里插入图片描述

然后右键resource.rc文件,选择插入图标和菜单

在这里插入图片描述

插入菜单举例右键打开:
在这里插入图片描述
里面的内容通过修改标明项即可自定义内容
ID可以设置为ID_FILE_EXIT
在这里插入图片描述

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"

LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	char szClassName[] = "MainClass";
	WNDCLASSEX wndclass;

	//用于描述主窗口的参数填充WNDCLASSEX结构
	wndclass.cbSize = sizeof(wndclass);  //结构的大小
	wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
	wndclass.lpfnWndProc = MainWndProc;   //窗口函数指针
	wndclass.cbClsExtra = 0;              //没有额外的类内存
	wndclass.cbWndExtra = 0;             //没有额外的窗口内存
	wndclass.hInstance = hInstance;      //实例句柄
	wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1);   //使用预定义图标
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);   //使用预定义光标
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
	wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定义的菜单
	wndclass.lpszClassName = szClassName;  //窗口类的名称
	wndclass.hIconSm = NULL;    //没有类的小图标

	//注册这个窗口类
	RegisterClassEx(&wndclass);
  
	//创建主窗口
	HWND hwnd = CreateWindowEx(
		0,                  //dwExSytle,扩展
		szClassName,        //lpClassName,窗口类名
		"My first Window!",    //lpWindowName,标题
		WS_OVERLAPPEDWINDOW,  //dwStyle,窗口风格
		CW_USEDEFAULT,    //X,初始化X坐标
		CW_USEDEFAULT,    //y,初始化Y坐标
		CW_USEDEFAULT,   //nWidth,宽度
		CW_USEDEFAULT,    //nHeight,高度
		NULL,          //hWindParent 父窗口句柄
		NULL,           //hMenu 菜单句柄
		hInstance,         //hInstance,程序实例句柄
        NULL	          //lpParam,用户数据	
		);

	if(hwnd == NULL)
	{
		MessageBox(NULL,"创建窗口出错!","error",MB_OK);
		return -1;
	}

    //显示窗口,刷新窗口客户区
	ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);


	//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
	MSG msg;

	while(GetMessage(&msg,NULL,0,0))
	{
		//转化为键盘消息
		TranslateMessage(&msg);
		//将消息发送到相应的窗口函数
		DispatchMessage(&msg);
		
	}

     //当GetMessage返回FALSE时程序结束
	return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	char szText[] = "最简单的窗口程序";
	switch(message)
	{
	case WM_PAINT: //窗口客户区需要重画
		{
		
			HDC hdc;
			PAINTSTRUCT ps;

			//使无效的客户区变的有效,并取得设备环境句柄
			hdc = BeginPaint(hwnd,&ps);

			//显示文字
			TextOut(hdc,10,10,szText,strlen(szText));
			EndPaint(hwnd,&ps);
			return 0;
		}
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case ID_FILE_EXIT:
			//向hwnd指定的窗口发送一个WM_CLOSE消息
			SendMessage(hwnd,WM_CLOSE,0,0);
			break;
		}
		return 0;
	case WM_CLOSE:    //任务管理器还是能干掉
			return 0; 
	case WM_DESTROY:  //正在销毁窗口
		//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
		PostQuitMessage(0);
		return 0;

		
	}
  //我们不处理的消息交给系统做默认处理
	return DefWindowProc(hwnd,message,wParam,lParam);

}

生成的图标和菜单如下所示:图标是瞎画的

在这里插入图片描述
单击菜单会发送WM_COMMAND消息,而wParam低字节包含了用户单击菜单的ID号

  • 接受键盘输入消息
    按下一个键时,windows会获得窗口消息队列中传递的WM_KEYDOWN或WM_SYSKEYDOWN消息。释放这个键时,会产生WM_KEYUP或WM_SYSTEMKEYUP消息。
  • wParam
    wParam包含敲击键的虚拟键码,也包含按键的ANSI码,比如敲“A”键,窗口会受到3个消息:
WM_KETDOWN    lParam的含义为虚拟键码“A”(0x41)
WM_CHAR             lParam的含义为虚拟键码“a”(0x61)
WM_KEYUP         lParam的含义为虚拟键码“A”(0x41)

示例:打字程序

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string>

LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	char szClassName[] = "MainClass";
	WNDCLASSEX wndclass;

	//用于描述主窗口的参数填充WNDCLASSEX结构
	wndclass.cbSize = sizeof(wndclass);  //结构的大小
	wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
	wndclass.lpfnWndProc = MainWndProc;   //窗口函数指针
	wndclass.cbClsExtra = 0;              //没有额外的类内存
	wndclass.cbWndExtra = 0;             //没有额外的窗口内存
	wndclass.hInstance = hInstance;      //实例句柄
	wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1);   //使用预定义图标
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);   //使用预定义光标
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
	wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定义的菜单
	wndclass.lpszClassName = szClassName;  //窗口类的名称
	wndclass.hIconSm = NULL;    //没有类的小图标

	//注册这个窗口类
	RegisterClassEx(&wndclass);
  
	//创建主窗口
	HWND hwnd = CreateWindowEx(
		0,                  //dwExSytle,扩展
		szClassName,        //lpClassName,窗口类名
		"My first Window!",    //lpWindowName,标题
		WS_OVERLAPPEDWINDOW,  //dwStyle,窗口风格
		CW_USEDEFAULT,    //X,初始化X坐标
		CW_USEDEFAULT,    //y,初始化Y坐标
		CW_USEDEFAULT,   //nWidth,宽度
		CW_USEDEFAULT,    //nHeight,高度
		NULL,          //hWindParent 父窗口句柄
		NULL,           //hMenu 菜单句柄
		hInstance,         //hInstance,程序实例句柄
        NULL	          //lpParam,用户数据	
		);

	if(hwnd == NULL)
	{
		MessageBox(NULL,"创建窗口出错!","error",MB_OK);
		return -1;
	}

    //显示窗口,刷新窗口客户区
	ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);


	//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
	MSG msg;

	while(GetMessage(&msg,NULL,0,0))
	{
		//转化为键盘消息
		TranslateMessage(&msg);
		//将消息发送到相应的窗口函数
		DispatchMessage(&msg);
		
	}

     //当GetMessage返回FALSE时程序结束
	return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	//str对象用于保存窗口客户区显示的字符串
	//为了使用string类,包含头文件#include <string>
	static std::string str;


	char szText[] = "最简单的窗口程序";
	switch(message)
	{
	case WM_CREATE:
		{
		//设置窗口的标题
			SetWindowText(hwnd,"最简陋的打字程序");
			return 0;
		}

	case WM_PAINT: //窗口客户区需要重画
		{
		
			HDC hdc;
			PAINTSTRUCT ps;

			//使无效的客户区变的有效,并取得设备环境句柄
			hdc = BeginPaint(hwnd,&ps);

			//显示文字
			TextOut(hdc,0,0,str.c_str(),str.length());
			EndPaint(hwnd,&ps);
			return 0;
		}
	case WM_CHAR:
		{
			//保存ANSI码
			str = str + char(wParam);
			//使整个客户区无效
			InvalidateRect(hwnd,NULL,0);
			return 0;
		
		}

	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case ID_FILE_EXIT:
			//向hwnd指定的窗口发送一个WM_CLOSE消息
			SendMessage(hwnd,WM_CLOSE,0,0);
			break;
		}
		return 0;
	//case WM_CLOSE:    //任务管理器还是能干掉
	//		return 0; 
	case WM_DESTROY:  //正在销毁窗口
		//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
		PostQuitMessage(0);
		return 0;

		
	}
  //我们不处理的消息交给系统做默认处理
	return DefWindowProc(hwnd,message,wParam,lParam);

}

在这里插入图片描述

  • 接受鼠标输入
按下弹起双击
左键WM_LBUTTONDOWNWM_LBUTTONUPWM_LBUTTONBLCLK
中键WM_MBUTTONDOWNWM_MBUTTONUPWM_MBUTTONBLCLK
右键WM_RBUTTONDOWNWM_RBUTTONUPWM_RBUTTONBLCLK

发送这些消息时,lParam包含了客户区坐标信息

xPos = LOWORD(lParam);
yPos = HIWORD(lParam);

转化为屏幕的坐标信息

BOOL ClientToScreen(HWND hWnd,LPPOINT lpPoint); //客户区转化为屏幕坐标
BOOL ScreenToClient(HWND hWnd,LPPOINT lpPoint); //屏幕坐标转化为客户区
  • wParam参数鼠标按钮信息,以MK_为前缀
MK_LBUTTON  左键按下
MK_MBUTTON  中间的键按下
MK_RBUTTON  右键按下
MK_SHIFT  <Shift>键按下
MK_CONTROL   <Ctrl>键按下
  • 示例:简陋打字程序之鼠标位置显示
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string>

LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	char szClassName[] = "MainClass";
	WNDCLASSEX wndclass;

	//用于描述主窗口的参数填充WNDCLASSEX结构
	wndclass.cbSize = sizeof(wndclass);  //结构的大小
	wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
	wndclass.lpfnWndProc = MainWndProc;   //窗口函数指针
	wndclass.cbClsExtra = 0;              //没有额外的类内存
	wndclass.cbWndExtra = 0;             //没有额外的窗口内存
	wndclass.hInstance = hInstance;      //实例句柄
	wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1);   //使用预定义图标
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);   //使用预定义光标
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
	wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定义的菜单
	wndclass.lpszClassName = szClassName;  //窗口类的名称
	wndclass.hIconSm = NULL;    //没有类的小图标

	//注册这个窗口类
	RegisterClassEx(&wndclass);
  
	//创建主窗口
	HWND hwnd = CreateWindowEx(
		0,                  //dwExSytle,扩展
		szClassName,        //lpClassName,窗口类名
		"My first Window!",    //lpWindowName,标题
		WS_OVERLAPPEDWINDOW,  //dwStyle,窗口风格
		CW_USEDEFAULT,    //X,初始化X坐标
		CW_USEDEFAULT,    //y,初始化Y坐标
		CW_USEDEFAULT,   //nWidth,宽度
		CW_USEDEFAULT,    //nHeight,高度
		NULL,          //hWindParent 父窗口句柄
		NULL,           //hMenu 菜单句柄
		hInstance,         //hInstance,程序实例句柄
        NULL	          //lpParam,用户数据	
		);

	if(hwnd == NULL)
	{
		MessageBox(NULL,"创建窗口出错!","error",MB_OK);
		return -1;
	}

    //显示窗口,刷新窗口客户区
	ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);


	//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
	MSG msg;

	while(GetMessage(&msg,NULL,0,0))
	{
		//转化为键盘消息
		TranslateMessage(&msg);
		//将消息发送到相应的窗口函数
		DispatchMessage(&msg);
		
	}

     //当GetMessage返回FALSE时程序结束
	return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	//str对象用于保存窗口客户区显示的字符串
	//为了使用string类,包含头文件#include <string>
	static std::string str;


	char szText[] = "最简单的窗口程序";
	switch(message)
	{
	case WM_CREATE:
		{
		//设置窗口的标题
			SetWindowText(hwnd,"最简陋的打字程序");
			return 0;
		}

	case WM_PAINT: //窗口客户区需要重画
		{
		
			HDC hdc;
			PAINTSTRUCT ps;

			//使无效的客户区变的有效,并取得设备环境句柄
			hdc = BeginPaint(hwnd,&ps);

			//显示文字
			TextOut(hdc,0,0,str.c_str(),str.length());
			EndPaint(hwnd,&ps);
			return 0;
		}
	case WM_CHAR:
		{
			//保存ANSI码
			str = str + char(wParam);
			//使整个客户区无效
			InvalidateRect(hwnd,NULL,0);
			return 0;
		
		}

	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case ID_FILE_EXIT:
			//向hwnd指定的窗口发送一个WM_CLOSE消息
			SendMessage(hwnd,WM_CLOSE,0,0);
			break;
		}
		return 0;
	case WM_LBUTTONDOWN:  //用户单击鼠标左键
		{
			char szPoint[56];
			//保存坐标信息
			wsprintf(szPoint,"X = %d,Y = %d",LOWORD(lParam),HIWORD(lParam));
			str = szPoint;
			if(wParam & MK_SHIFT)
				str = str+" Shift Key is down";
			InvalidateRect(hwnd,NULL,1);
			return 0;		
		}
	//case WM_CLOSE:    //任务管理器还是能干掉
	//		return 0; 
	case WM_DESTROY:  //正在销毁窗口
		//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
		PostQuitMessage(0);
		return 0;

		
	}
  //我们不处理的消息交给系统做默认处理
	return DefWindowProc(hwnd,message,wParam,lParam);

}

在这里插入图片描述

  • 示例:简陋打字程序完成版
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string>

LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	char szClassName[] = "MainClass";
	WNDCLASSEX wndclass;

	//用于描述主窗口的参数填充WNDCLASSEX结构
	wndclass.cbSize = sizeof(wndclass);  //结构的大小
	wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
	wndclass.lpfnWndProc = MainWndProc;   //窗口函数指针
	wndclass.cbClsExtra = 0;              //没有额外的类内存
	wndclass.cbWndExtra = 0;             //没有额外的窗口内存
	wndclass.hInstance = hInstance;      //实例句柄
	wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1);   //使用预定义图标
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);   //使用预定义光标
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
	wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定义的菜单
	wndclass.lpszClassName = szClassName;  //窗口类的名称
	wndclass.hIconSm = NULL;    //没有类的小图标

	//注册这个窗口类
	RegisterClassEx(&wndclass);
  
	//创建主窗口
	HWND hwnd = CreateWindowEx(
		0,                  //dwExSytle,扩展
		szClassName,        //lpClassName,窗口类名
		"My first Window!",    //lpWindowName,标题
		WS_OVERLAPPEDWINDOW,  //dwStyle,窗口风格
		CW_USEDEFAULT,    //X,初始化X坐标
		CW_USEDEFAULT,    //y,初始化Y坐标
		CW_USEDEFAULT,   //nWidth,宽度
		CW_USEDEFAULT,    //nHeight,高度
		NULL,          //hWindParent 父窗口句柄
		NULL,           //hMenu 菜单句柄
		hInstance,         //hInstance,程序实例句柄
        NULL	          //lpParam,用户数据	
		);

	if(hwnd == NULL)
	{
		MessageBox(NULL,"创建窗口出错!","error",MB_OK);
		return -1;
	}

    //显示窗口,刷新窗口客户区
	ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);


	//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
	MSG msg;

	while(GetMessage(&msg,NULL,0,0))
	{
		//转化为键盘消息
		TranslateMessage(&msg);
		//将消息发送到相应的窗口函数
		DispatchMessage(&msg);
		
	}

     //当GetMessage返回FALSE时程序结束
	return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	//str对象用于保存窗口客户区显示的字符串
	//为了使用string类,包含头文件#include <string>
	static std::string str;


	char szText[] = "最简单的窗口程序";
	switch(message)
	{
	case WM_CREATE:
		{
		//设置窗口的标题
			SetWindowText(hwnd,"最简陋的打字程序");
			return 0;
		}

	case WM_PAINT: //窗口客户区需要重画
		{
		
			HDC hdc;
			PAINTSTRUCT ps;

			//使无效的客户区变的有效,并取得设备环境句柄
			hdc = BeginPaint(hwnd,&ps);
            
			//设置输出文本的背景颜色和文字颜色
			SetTextColor(hdc,RGB(255,0,0)); //红色文本
			SetBkColor(hdc,GetSysColor(COLOR_3DFACE));  //windows预定显示元素COLOR_3DFACE 


			//显示文字
			TextOut(hdc,0,0,str.c_str(),str.length());
			EndPaint(hwnd,&ps);
			return 0;
		}
	case WM_CHAR:
		{
			//保存ANSI码
			str = str + char(wParam);
			//使整个客户区无效
			InvalidateRect(hwnd,NULL,0);
			return 0;
		
		}

	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case ID_FILE_EXIT:
			//向hwnd指定的窗口发送一个WM_CLOSE消息
			SendMessage(hwnd,WM_CLOSE,0,0);
			break;
		}
		return 0;
	case WM_LBUTTONDOWN:  //用户单击鼠标左键
		{
			char szPoint[56];
			//保存坐标信息
			wsprintf(szPoint,"X = %d,Y = %d",LOWORD(lParam),HIWORD(lParam));
			str = szPoint;
			if(wParam & MK_SHIFT)
				str = str+" Shift Key is down";
			InvalidateRect(hwnd,NULL,1);
			return 0;		
		}
	//case WM_CLOSE:    //任务管理器还是能干掉
	//		return 0; 
	case WM_DESTROY:  //正在销毁窗口
		//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
		PostQuitMessage(0);
		return 0;

		
	}
  //我们不处理的消息交给系统做默认处理
	return DefWindowProc(hwnd,message,wParam,lParam);

}

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值