其他分享
首页 > 其他分享> > Win32从入门到放弃

Win32从入门到放弃

作者:互联网

文章目录


1.应用程序分类

1.1.分类

1.2.应用程序对比

控制台应用程序

#include <stdio.h>
int main(){
	printf("hello world\n");

	return 0;
}

2.开发工具和库

2.1.编译工具

2.2.库和头文件

2.3.相关函数

2.3.1.WinMain

int WINAPI WinMain(  HINSTANCE hInstance,      // handle to current instance当前程序的实例句柄
  HINSTANCE hPrevInstance,  // handle to previous instance当前程序前一个实例句柄
  LPSTR lpCmdLine,          // command line命令行参数字符串
  int nCmdShow              // show state窗口显示方式
  );

2.3.2.MessageBox

int MessageBox(  HWND hWnd,          // handle to owner window父窗口句柄
  LPCTSTR lpText,     // text in message box显示在消息框中的文字
  LPCTSTR lpCaption,  // message box title显示在标题栏的文字
  UINT uType          // message box style消息框中的按钮、图标显示类型
  );//返回点击的按钮ID

2.4.程序编译过程

#include <windows.h>
int WinMain(HINSTANCE hIns,
			HINSTANCE hPreIns,
			LPSTR lpCmdLine,
			int nCmdShow){
	MessageBox(NULL,"hello world","Information",MB_YESNOCANCEL|MB_ICONERROR);
	return 0;
}

2.5.编译rc文件

//Hello.rc
100 ICON chuhe.ico

在这里插入图片描述

3.第一个Windows窗口

3.1.窗口创建过程

3.2.代码示例

#include <windows.h>

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

4.字符编码

4.1.编码历史背景

4.2.DBCS和UNICODE

在这里插入图片描述

4.3.宽字节字符

#include <Windows.h>
#include <stdio.h>
void C_char(){
	char* pszText="Hello char";
	int len=strlen(pszText);
	printf("%s %d\n",pszText,len);
}
void W_char(){
	wchar_t* pszText=L"Hello wchar";
	int len=wcslen(pszText);
	wprintf(L"%s %d\n",pszText,len);
}


int main(){
	C_char();
	W_char();	
	getchar();
	return 0;
}

4.4.TCHAR

4.5.打印UNICODE

#define UNICODE
#include <Windows.h>
#include <stdio.h>

void PrintUnicode(){
	wchar_t* pszText=L"锄禾日当午\n";
	//char* pszText="锄禾日当午\n";	
	HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);//标准输出句柄
	WriteConsole(hOut,pszText,wcslen(pszText),NULL,NULL);
	
	
}
int main(){
	PrintUnicode();
	getchar();
	return 0;
}

4.6.为什么要更改成多字符集

在这里插入图片描述

LPSTR==char*LPSTR==const char*
LPWSTR==wchar_t*LPCWSTR==const wchar_t*
LPTSTR==TCHAR*LPCTSTR==const TCHAR*

5.注册窗口类

5.1.窗口类的概念

5.2.窗口类的分类

5.3.系统窗口类

#include <windows.h>



int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){

	//创建窗口
	HWND hWnd=CreateWindow("Button","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

5.4.全局及局部窗口类

6.窗口创建

6.1.窗口创建

HWND CreateWindowEx( 
				  DWORD dwExStyle,      // extended window style窗口的扩展风格
				  LPCTSTR lpClassName,  // registered class name已经注册的窗口类名称
				  LPCTSTR lpWindowName, // window name 窗口标题栏的名字 
				  DWORD dwStyle,        // window style窗口的基本风格
				  int x,                // horizontal position of window窗口左上角水平坐标位置
				  int y,                // vertical position of window窗口左上角垂直坐标位置
				  int nWidth,           // window width  窗口宽度
				  int nHeight,          // window height窗口高度
				  HWND hWndParent,      // handle to parent or owner window窗口父窗口句柄
				  HMENU hMenu,          // menu handle or child identifier窗口菜单句柄
				  HINSTANCE hInstance,  // handle to application instance应用程序实例句柄
				  LPVOID lpParam        // window-creation data窗口创建时附加参数
				  );//创建成功返回窗口句柄

6.2.窗口创建执行过程

6.3.子窗口创建

#include <windows.h>

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lPARAM){

	switch(msgID){
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0,相当于抛了一个WM_QUIT
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lPARAM);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindowEx(0,"Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);

	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=DefWindowProc;
	wc.lpszClassName="Child";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	HWND hChild1=CreateWindowEx(0,"Child","c1",WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,0,0,200,200,hWnd,NULL,hIns,NULL);
	HWND hChild2=CreateWindowEx(0,"Child","c2",WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,200,0,200,200,hWnd,NULL,hIns,NULL);


	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

在这里插入图片描述

7.消息基础

7.1.消息的概念和作用

7.2.窗口处理函数

7.3.浅谈消息相关函数

8.常见消息

8.1.WM_DESTROY

8.2.WM_SYSCOMMAND

8.3.WM_CREATE

8.4.WM_SIZE

8.5.WM_QUIT

8.6.WM_PAINT

详见WM_PAINT

8.7.WM_COMMAND

点击菜单触发的WM_COMMAND
点击加速键触发的WM_COMMAND

8.8.WM_INITDIALOG

详见对话框的消息

9.Win32窗口额外创建一个控制台窗口

#include <windows.h>
#include <stdio.h>
HANDLE g_hOutput=0;//1、定义全局变量,标准输出句柄
void OnSize(HWND hWnd,LPARAM lParam){
	short nWidth=LOWORD(lParam);
	short nHeight=HIWORD(lParam);
	char szText[256]={0};
	sprintf(szText,"WM_SIZE:宽:%d,高:%d\n",nWidth,nHeight);
	WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);//3、往控制台窗口写入信息
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lPARAM){

	switch(msgID){
	case WM_DESTROY:		
		PostQuitMessage(0);
		break;
	case WM_SYSCOMMAND:		
		break;
	case WM_SIZE:
		OnSize(hWnd,lPARAM);
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lPARAM);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	AllocConsole();//2、增加dos窗口
	g_hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL; 
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindowEx(0,"Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);

	
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

10.消息循环原理

10.1.消息循环的阻塞

#include <windows.h>
#include <stdio.h>
HANDLE g_hOutput=0;//1、全局变量,定义标准输出句柄
void OnSize(HWND hWnd,LPARAM lParam){
	short nWidth=LOWORD(lParam);
	short nHeight=HIWORD(lParam);
	char szText[256]={0};
	sprintf(szText,"WM_SIZE:宽:%d,高:%d\n",nWidth,nHeight);
	WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);//3、往控制台窗口写入信息
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lPARAM){

	switch(msgID){
	case WM_DESTROY:		
		PostQuitMessage(0);
		break;
	case WM_SYSCOMMAND:		
		break;
	case WM_SIZE:
		OnSize(hWnd,lPARAM);
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lPARAM);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	AllocConsole();//2、增加dos窗口
	g_hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL; 
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindowEx(0,"Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);

	
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	//while(GetMessage(&nMsg,NULL,0,0)){
	//	TranslateMessage(&nMsg);
	//	DispatchMessage(&nMsg);//将消息交给窗口函数处理
	//}
	while(1){
		if(PeekMessage(&nMsg,NULL,0,0,PM_NOREMOVE)){
			//有消息
			if(GetMessage(&nMsg,NULL,0,0)){
				TranslateMessage(&nMsg);
				DispatchMessage(&nMsg);//将消息交给窗口函数处理
			}else{
				return 0;
			}
		}else{
			//无消息,空闲处理
			WriteConsole(g_hOutput,"OnIdle",strlen("OnIdle"),NULL,NULL);

		}
	}
	return 0;
}

10.2.发送消息

10.1.消息分类

#include <windows.h>
#include <stdio.h>
#define WM_MYMESSAGE WM_USER+1001	//即0x400+1001
HANDLE g_hOutput=0;
void OnSize(HWND hWnd,LPARAM lParam){
	short nWidth=LOWORD(lParam);
	short nHeight=HIWORD(lParam);
	char szText[256]={0};
	sprintf(szText,"WM_SIZE:宽:%d,高:%d\n",nWidth,nHeight);
	PostMessage(hWnd,WM_MYMESSAGE,1,2);//发送自己定义的消息
	SendMessage(hWnd,WM_MYMESSAGE,1,2);//发送自己定义的消息
	WriteConsole(g_hOutput,szText,strlen(szText),NULL,NULL);
}
void OnMyMessage(HWND hWnd,WPARAM wParam,LPARAM lParam){
	char szText[256]={0};
	sprintf(szText,"自定义消息被处理:wParam=%d,lParam=%d\n",wParam,lParam);
	MessageBox(hWnd,szText,"Infor",MB_OK);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_MYMESSAGE:
		OnMyMessage(hWnd,wParam,lParam);
		break;
	case WM_DESTROY:		
		//PostQuitMessage(0);可以使GetMessage函数返回0,抛出了一个WM_QUIT消息
		PostMessage(hWnd,WM_QUIT,0,0);
		break;
	case WM_SYSCOMMAND:		
		break;
	case WM_SIZE:
		OnSize(hWnd,lParam);
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	AllocConsole();
	g_hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL; 
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindowEx(0,"Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);

	
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	//while(GetMessage(&nMsg,NULL,0,0)){
	//	TranslateMessage(&nMsg);
	//	DispatchMessage(&nMsg);//将消息交给窗口函数处理
	//}
	while(1){
		if(PeekMessage(&nMsg,NULL,0,0,PM_NOREMOVE)){
			//有消息
			if(GetMessage(&nMsg,NULL,0,0)){
				TranslateMessage(&nMsg);
				DispatchMessage(&nMsg);//将消息交给窗口函数处理
			}else{
				return 0;
			}
		}else{
			//无消息,空闲处理
			WriteConsole(g_hOutput,"OnIdle",strlen("OnIdle"),NULL,NULL);

		}
	}
	return 0;
}

11.消息队列

11.1.消息队列的概念

11.2.消息队列分类

11.3.消息和队列关系

11.4.深淡GetMessage原理

11.5.WM_PAINT消息

处理WM_PAINT消息例子,如下:

#include <windows.h>
HANDLE g_hOutput=0;
void OnPaint(HWND hWnd){
	char* pszText="WM_PAINT\n";
	WriteConsole(g_hOutput,pszText,strlen(pszText),NULL,NULL);

	PAINTSTRUCT ps={0};
	HDC hdc=BeginPaint(hWnd,&ps);
	TextOutA(hdc,100,100,"hello",5);
	EndPaint(hWnd,&ps);
	//以上绘图代码,必须放在处理WM_PAINT消息时调用 


}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lPARAM){

	switch(msgID){
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_LBUTTONDOWN:
		InvalidateRect(hWnd,NULL,TRUE);//鼠标点击时,会调用InvalidateRect函数,从而产生WM_PAINT消息。
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lPARAM);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	AllocConsole();
	g_hOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

12.键盘消息

12.1.键盘消息分类

12.2.字符消息WM_CHAR

12.3.字盘消息和WM_CHAR消息举例

#include <windows.h>
#include <stdio.h>
HANDLE h_gOutput=0;
void OnKeyDown(HWND hWnd,WPARAM wParam,LPARAM lParam){
	char szText[256]={0};
	sprintf(szText,"WM_KEYDOWN:键码值=%d\n",wParam);
	WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);

}
void OnKeyUp(HWND hWnd,WPARAM wParam,LPARAM lParam){
	char szText[256]={0};
	sprintf(szText,"WM_KEYUP:键码值=%d\n",wParam);
	WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
}
void OnChar(HWND hWnd,WPARAM wParam){
	char szText[256]={0};
	sprintf(szText,"WM_CHAR:wParam=%d\n",wParam);
	WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_CHAR:
		OnChar(hWnd,wParam);
		break;
	case WM_KEYDOWN:
		OnKeyDown(hWnd,wParam,lParam);
		break;
	case WM_KEYUP:
		OnKeyUp(hWnd,wParam,lParam);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	AllocConsole();
	h_gOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

13.鼠标消息

13.1.鼠标消息分类

13.2.鼠标基本消息

13.3.鼠标双击消息

13.4.鼠标滚轮消息

13.5.鼠标消息的举例代码

#include <windows.h>
#include <stdio.h>
HANDLE h_gOutput=0;
void OnLButtonDown(HWND hWnd,WPARAM wParam,LPARAM lParam){
	char szText[256]={0};	
	sprintf(szText,"WM_LBUTTONDOWN:按键状态wParam=%d,x=%d,y=%d\n",wParam,LOWORD(lParam),HIWORD(lParam));
	WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
}
void OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam){
	char szText[256]={0};
	sprintf(szText,"WM_LBUTTONUP:按键状态wParam=%d,x=%d,y=%d\n",wParam,LOWORD(lParam),HIWORD(lParam));
	WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
}
void onm ouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam){
	char szText[256]={0};
	sprintf(szText,"WM_MOUSEMOVE:按键状态wParam=%d,x=%d,y=%d\n",wParam,LOWORD(lParam),HIWORD(lParam));
	WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
	
}
void OnLButtonDblClk(HWND hWnd,WPARAM wParam,LPARAM lParam){
	char szText[256]={0};	
	sprintf(szText,"WM_LBUTTONDBLCLK:按键状态wParam=%d,x=%d,y=%d\n",wParam,LOWORD(lParam),HIWORD(lParam));
	WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
}
void onm ouseWheel(HWND hWnd,WPARAM wParam,LPARAM lParam){
	char szText[256]={0};
	short nDelta=HIWORD(wParam);//偏移量
	sprintf(szText,"WM_MOUSEWHEEL:按钮状态%d,偏移量%d,滚动方向:%s,x=%d,y=%d\n",LOWORD(wParam),nDelta,nDelta>0?"前":"后",LOWORD(lParam),HIWORD(lParam));
	WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_MOUSEWHEEL:
		OnMouseWheel(hWnd,wParam,lParam);
		break;
	case WM_LBUTTONDBLCLK:
		OnLButtonDblClk(hWnd,wParam,lParam);
		break;
	case WM_MOUSEMOVE:
		OnMouseMove(hWnd,wParam,lParam);
		break;
	case WM_LBUTTONDOWN:
		OnLButtonDown(hWnd,wParam,lParam);
		break;
	case WM_LBUTTONUP:
		OnLButtonUp(hWnd,wParam,lParam);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	AllocConsole();
	h_gOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

14.定时器消息

14.1.定时器消息介绍

14.2.创建、销毁定时器

14.3.定时器代码示例

#include <windows.h>
#include <stdio.h>

HANDLE h_gOutput=0;
void OnTimer(HWND hWnd,WPARAM wParam){
	char szText[256]={0};
	
	switch(wParam){
	case 1:
		sprintf(szText,"触发第1个定时器,ID=%d\n",wParam);
		WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
		break;
	case 2:
		sprintf(szText,"触发第2个定时器,ID=%d\n",wParam);
		WriteConsole(h_gOutput,szText,strlen(szText),NULL,NULL);
		break;
	}
}


LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_TIMER:
		OnTimer(hWnd,wParam);
		break;
	case WM_CREATE:
		SetTimer(hWnd,1,1000,NULL);
		SetTimer(hWnd,2,2000,NULL);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	AllocConsole();
	h_gOutput=GetStdHandle(STD_OUTPUT_HANDLE);
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

15.菜单资源

15.1.菜单分类

HMENU类型表示菜单(菜单句柄),ID表示菜单项。

15.2.资源相关

15.3.菜单资源使用

15.4.加载菜单的三种方法

15.4.1. 注册窗口类时设置菜单

#include <windows.h>
#include "resource.h"

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){	
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	g_hInstance=hIns;
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";	
	wc.lpszMenuName=(char*)IDR_MENU1;//注册窗口类时设置菜单
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

15.4.2. 创建窗口传参设置菜单

#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	g_hInstance=hIns;
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;	
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	//***************************创建窗口传参设置菜单
	HMENU hMenu=LoadMenu(hIns,(char*)IDR_MENU1);
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,hMenu,hIns,NULL);

	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

15.4.3. 在主窗口WM_CREATE消息中利用SetMenu函数设置菜单

#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance=0;
void OnCreate(HWND hWnd){
	HMENU hMenu=LoadMenu(g_hInstance,(char*)IDR_MENU1);
	SetMenu(hWnd,hMenu);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_CREATE:
		OnCreate(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	g_hInstance=hIns;
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;	
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

15.5.命令消息处理WM_COMMAND

命令消息处理代码示例

#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance=0;
void OnCreate(HWND hWnd){
	HMENU hMenu=LoadMenu(g_hInstance,(char*)IDR_MENU1);
	SetMenu(hWnd,hMenu);
}
void OnCommand(HWND hWnd,WPARAM wParam){
	switch(LOWORD(wParam)){
	case ID_NEW:
		MessageBox(hWnd,"新建被点击","Info",MB_OK);
		break;
	case ID_EXIT:
		MessageBox(hWnd,"退出被点击","Info",MB_OK);
		break;
	case ID_ABOUT:
		MessageBox(hWnd,"关于被点击","Info",MB_OK);
		break;
	}
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_COMMAND:
		OnCommand(hWnd,wParam);
		break;
	case WM_CREATE:
		OnCreate(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	g_hInstance=hIns;
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	//wc.lpszMenuName=(char*)IDR_MENU1;//菜单
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	/*HMENU hMenu=LoadMenu(hIns,(char*)IDR_MENU1);
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,hMenu,hIns,NULL);*/
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

15.6.菜单项状态

15.7.上下文菜单

16.图标资源

17.光标资源

17.1.光标资源的介绍

17.2.设置光标资源的两种方法

HCURSOR SetCursor(  HCURSOR hCursor   // handle to cursor);

17.3.WM_SETCURSOR消息

17.4.示例代码

#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstancee=0;

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_SETCURSOR:
		if(LOWORD(lParam)==HTCLIENT){
			HCURSOR hCur=LoadCursor(g_hInstancee,(char*)IDC_CURSOR2);
			SetCursor(hCur);
			return 0;//不加,执行return DefWindowProc(hWnd,msgID,wParam,lParam);时,会修改成系统注册窗口时的光标
		}else{
			//非客户区,不处理。系统默认处理函数会处理
		}				
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	g_hInstancee=hIns;
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=LoadCursor(hIns,(char*)IDC_CURSOR1);//加载光标,只能在客户区显示该光标
	wc.hIcon=LoadIcon(hIns,(char*)IDI_ICON1);//加载图标资源
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

18.字符串资源

代码示例:
在这里插入图片描述

#include <windows.h>
#include "resource.h"

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){

	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	char szText[256]={0};
	LoadString(hIns,IDS_WND,szText,256);
	HWND hWnd=CreateWindow("Main",szText,WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

19.加速键资源

加速键的使用
在这里插入图片描述
在这里插入图片描述
代码示例

#include <windows.h>
#include "resource.h"
void OnCommand(HWND hWnd,WPARAM wParam){
	switch(LOWORD(wParam)){
	case ID_NEW:
		if(HIWORD(wParam)==0)
			MessageBox(hWnd,"新建菜单项被点击","Info",MB_OK);
		else if(HIWORD(wParam)==1)
			MessageBox(hWnd,"CTRL+M被点击","Info",MB_OK);
		break;
	}
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_COMMAND:
		OnCommand(hWnd,wParam);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){

	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=(char*)IDR_MENU1;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	HACCEL hAccel=LoadAccelerators(hIns,(char*)IDR_ACCELERATOR1);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		if(!TranslateAccelerator(hWnd,hAccel,&nMsg)){
			//如果不是加速键
			TranslateMessage(&nMsg);
			DispatchMessage(&nMsg);//将消息交给窗口函数处理
		}

	}
	return 0;
}

20.绘图编程

20.1.绘图基础

20.2.基本图形绘制

代码示例

#include <windows.h>

void OnPaint(HWND hWnd){
	PAINTSTRUCT ps={0};
	HDC hdc=BeginPaint(hWnd,&ps);
	SetPixel(hdc,100,100,RGB(255,0,0));//绘制点

	LineTo(hdc,100,0);
	MoveToEx(hdc,0,0,NULL);
	LineTo(hdc,0,100);

	Rectangle(hdc,100,100,300,300);
	Ellipse(hdc,100,100,300,300);
	EndPaint(hWnd,&ps);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

20.3.GDI绘图对象

20.3.1.画笔

只能删除不被DC使用的画笔,所在在释放前,必须将画笔从DC中取出。

画笔示例代码:

#include <windows.h>

void OnPaint(HWND hWnd){
	PAINTSTRUCT ps={0};
	HDC hdc=BeginPaint(hWnd,&ps);
	HPEN hPen=CreatePen(PS_SOLID,5,RGB(255,0,0));//创建画笔
	HGDIOBJ nOldPen=SelectObject(hdc,hPen);	

	Rectangle(hdc,100,100,300,300);
	Ellipse(hdc,100,100,300,300);

	SelectObject(hdc,nOldPen);
	DeleteObject(hPen);
	EndPaint(hWnd,&ps);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

20.3.2.画刷

示例代码:

#include <windows.h>

void OnPaint(HWND hWnd){
	PAINTSTRUCT ps={0};
	HDC hdc=BeginPaint(hWnd,&ps);
	HPEN hPen=CreatePen(PS_SOLID,5,RGB(255,0,0));//创建画笔
	HGDIOBJ nOldPen=SelectObject(hdc,hPen);	//选中画笔

	HBRUSH hBrush=CreateSolidBrush(RGB(0,255,0));//创建实心画刷
//  HBRUSH hBrush=CreateHatchBrush(HS_CROSS,RGB(0,255,0));//创建纹理画刷
//	HGDIOBJ hBrush=GetStockObject(NULL_BRUSH);//由系统维护的透明画刷
	HGDIOBJ nOldBrush=SelectObject(hdc,hBrush);//选中画刷

	Rectangle(hdc,100,100,300,300);
	Ellipse(hdc,100,100,300,300);

	SelectObject(hdc,nOldPen);//恢复原来的画笔
	SelectObject(hdc,nOldBrush);//恢复原来的画刷
	DeleteObject(hPen);//删除画笔
	DeleteObject(hBrush);//删除画刷
	EndPaint(hWnd,&ps);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

实心画刷效果
在这里插入图片描述

纹理画刷效果
在这里插入图片描述

21.位图

21.1.位图绘制

21.1.1. 位图相关

21.1.2. 位图的使用

21.1.3. 代码示例

#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance=0;
void BrawBmp(HDC hdc){
	HBITMAP hBmp=LoadBitmap(g_hInstance,(CHAR*)IDB_BITMAP1);
	//创建一个内存DC,并构建一个虚拟区域,并且内存DC在虚拟区域中绘图
	HDC hMemdc=CreateCompatibleDC(hdc);
	//将位图数据送给内存DC,内存DC在虚拟区域中将位图绘制出来。
	HGDIOBJ nOldBmp=SelectObject(hMemdc,hBmp);
	//1:1成像,将虚拟区域中绘制好的图像成像到窗口中
	BitBlt(hdc,100,100,48,48,hMemdc,0,0,SRCCOPY);
	//缩放成像,缩小成24*24
	StretchBlt(hdc,200,200,24,24,hMemdc,0,0,48,48,SRCCOPY);
	//缩放成像,放大成96*96
	StretchBlt(hdc,300,300,96,96,hMemdc,0,0,48,48,SRCCOPY);
	SelectObject(hMemdc,nOldBmp);
	DeleteObject(hBmp);
	DeleteObject(hMemdc);
}

void OnPaint(HWND hWnd){
	PAINTSTRUCT ps={0};
	HDC hdc=BeginPaint(hWnd,&ps);
	BrawBmp(hdc);
	
	EndPaint(hWnd,&ps);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	g_hInstance=hIns;
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

22.文本绘制

22.1.文本绘制

22.2.文字颜色和背景

22.3.字体

22.3.1.字体介绍

22.3.2.字体的使用

22.3.3. 代码示例

#include <windows.h>
#include <stdio.h>
void OnPaint(HWND hWnd){
	PAINTSTRUCT ps={0};
	HDC hdc=BeginPaint(hWnd,&ps);	

	SetTextColor(hdc,RGB(255,0,0));//设置字体颜色
	SetBkColor(hdc,RGB(0,255,0));//设置背景字体颜色,只适于OPAQUE模式
	SetBkMode(hdc,TRANSPARENT);//设置背景字体透明

	HFONT hFont=CreateFont(30,0,45,0,900,1,1,1,GB2312_CHARSET,0,0,0,0,"微软雅黑");
	HGDIOBJ nOldFont=SelectObject(hdc,hFont);


	char szText[256]="Hello word!";	
	TextOut(hdc,100,100,szText,strlen(szText));

	RECT rt;
	rt.left=100;
	rt.top=150;
	rt.right=200;
	rt.bottom=200;
	//Rectangle(hdc,100,150,200,200);
	DrawText(hdc,szText,strlen(szText),&rt,DT_LEFT|DT_TOP|DT_WORDBREAK|DT_NOCLIP);
	SelectObject(hdc,nOldFont);
	DeleteObject(hFont);
	EndPaint(hWnd,&ps);

}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_PAINT:
		OnPaint(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=NULL;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

23.对话框

23.1.对话框原理

23.2.模式对话框

23.2.1. 创建对话框

INT_PTR DialogBox(  
	  HINSTANCE hInstance,  // handle to module
	  LPCTSTR lpTemplate,   // dialog box template对话框资源ID
	  HWND hWndParent,      // handle to owner window
	  DLGPROC lpDialogFunc  // dialog box procedure自定义函数
  );

23.2.2. 对话框的关闭

BOOL EndDialog(  
	  HWND hDlg,        // handle to dialog box
	  INT_PTR nResult   // value to return
  );

23.2.3. 对话框的消息

23.2.4. 代码示例

#include <windows.h>
#include "resource.h"
HINSTANCE g_hIns=0;
INT_PTR CALLBACK DialogProc(  
	HWND hwndDlg,  // handle to dialog box
	UINT uMsg,     // message  
	WPARAM wParam, // first message parameter
	LPARAM lParam  // second message parameter
	){
		switch(uMsg){
		case WM_INITDIALOG:
			MessageBox(hwndDlg,"WM_INITDIALOG","Info",MB_OK);
			break;
		case WM_SYSCOMMAND:
			if(wParam==SC_CLOSE){
				//销毁模式对话框
				EndDialog(hwndDlg,100);
			}
			break;
		} 
		return FALSE;
}
void OnCommand(HWND hWnd,WPARAM wParam){
	switch(LOWORD(wParam)){
	case ID_MODEL:
		int nRet=DialogBox(g_hIns,(char*)IDD_DIALOG1,hWnd,DialogProc);
		if(nRet==100)
			MessageBox(hWnd,"successful","Info",MB_OK);
		break;
	}
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam){

	switch(msgID){
	case WM_COMMAND:
		OnCommand(hWnd,wParam);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd,msgID,wParam,lParam);
}

int CALLBACK WinMain(HINSTANCE hIns,HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow){
	g_hIns=hIns;
	//注册窗口类
	WNDCLASS wc={0};
	wc.cbClsExtra=0;
	wc.cbWndExtra=0;
	wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor=NULL;
	wc.hIcon=NULL;
	wc.hInstance=hIns;
	wc.lpfnWndProc=WndProc;
	wc.lpszClassName="Main";
	wc.lpszMenuName=(CHAR*)IDR_MENU1;
	wc.style=CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);
	//创建窗口
	HWND hWnd=CreateWindow("Main","Window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg={0};
	while(GetMessage(&nMsg,NULL,0,0)){
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口函数处理
	}
	return 0;
}

23.3.无模式对话框

23.3.1.创建对话框

HWND CreateDialog(  
	  HINSTANCE hInstance,  // handle to module
	  LPCTSTR lpTemplate,   // dialog box template name模板资源ID
	  HWND hWndParent,      // handle to owner window
	  DLGPROC lpDialogFunc  // dialog box procedure自定义函数
  );

23.3.2. 对话框的关闭

24.静态库

24.1.静态库特点

24.2.C语言静态库

24.3.C++语言静态库

//给编译器看的
#include <iostream>
using namespace std;
int CPPlib_add(int a,int b);
int CPPlib_sub(int a,int b);
//调用C语言静态库Clib.lib中的函数
extern "C" int Clib_add(int a,int b);
extern "C" int Clib_sub(int a,int b);

//给链接器看的
#pragma comment(lib,"../Debug/CPPlib.lib")//?CPPlib_sub@@YAHHH@Z、?CPPlib_add@@YAHHH@Z
#pragma comment(lib,"../Debug/Clib.lib")//Clib_add、Clib_sub
int main(){
	int sum=0,sub=0;
	sum=CPPlib_add(1,2);//?CPPlib_sub@@YAHHH@Z
	sub=CPPlib_sub(3,5);//?CPPlib_add@@YAHHH@Z
	cout<<"sum="<<sum<<",sub"<<sub<<endl;
	sum=Clib_add(1,2);//?Clib_sub@@YAHHH@Z
	sub=Clib_sub(2,3);//?Clib_add@@YAHHH@Z
	cout<<"sum="<<sum<<",sub"<<sub<<endl;
	getchar();
	return 0;
}

25.动态库

25.1.动态库特点

25.1.动态库创建

25.2.动态库导出的两种方法

25.2.1.声明导出

CPPdll.cpp

_declspec(dllexport)int CPPdll_add(int a,int b){
	return a+b;
}

_declspec(dllexport)int CPPdll_sub(int a,int b){
	return a-b;
}

_declspec(dllexport)int CPPdll_mul(int a,int b){
	return a*b;
}

25.2.2. 模块定义文件.def

LIBRARY CPPdll  //库
EXPORTS			//库导出表
	CPPdll_add @1//导出的函数
	CPPdll_sub @2//导出的函数

CPPdll.dll

int CPPdll_add(int a,int b){
	return a+b;
}

int CPPdll_sub(int a,int b){
	return a-b;
}

_declspec(dllexport)int CPPdll_mul(int a,int b){
	return a*b;
}

CPPdll.def

LIBRARY CPPdll
EXPORTS
	CPPdll_add @1
	CPPdll_sub @2

UseShow.cpp

#include <windows.h>
#include <iostream>
using namespace std;
typedef int(*ADD)(int a,int b);
typedef int(*SUB)(int a,int b);
typedef int(*MUL)(int a,int b);

int main(){
	HINSTANCE hDll=LoadLibrary("CPPdll.dll");		
	cout<<"hDll:"<<hDll<<endl;
	ADD myAdd=(ADD)GetProcAddress(hDll,"CPPdll_add");//?CPPdll_add@@YAHHH@Z
	cout<<"myAdd:"<<myAdd<<endl;
	int sum=myAdd(1,2);
	cout<<"sum="<<sum<<endl;
	SUB mySub=(SUB)GetProcAddress(hDll,"CPPdll_sub");
	cout<<"mySub:"<<mySub<<endl;
	int sub=mySub(2,3);
	cout<<"sub="<<sub<<endl;
	MUL myMul=(MUL)GetProcAddress(hDll,"?CPPdll_mul@@YAHHH@Z");
	cout<<"myMul:"<<myMul<<endl;
	int mul=myMul(3,4);
	cout<<"mul="<<mul<<endl;
	FreeLibrary(hDll);
	getchar();
	return 0;
	
}

25.1.动态库的使用

25.1.1.隐式链接(操作系统负责使动态库执行)

代码示例

#include <iostream>
using namespace std;
_declspec(dllimport)int CPPdll_add(int a,int b);
_declspec(dllimport)int CPPdll_sub(int a,int b);
_declspec(dllimport)int CPPdll_mul(int a,int b);
#pragma comment(lib,"../Debug/CPPdll.lib")//通知链接器抓取编号和DLL文件名
int main(){
	int sum=CPPdll_add(1,2);
	int sub=CPPdll_sub(2,3);
	int mul=CPPdll_mul(3,4);
	cout<<"sum="<<sum<<",sub="<<sub<<".mul="<<mul<<endl;
	return 0;
}

25.1.2.显示链接(程序员自己负责动态库执行)

代码示例详见

25.1.动态库中封装类

代码示例:

#include <iostream>
using namespace std;
#include "../ClassDll/ClassDll.h"
#pragma  comment(lib,"../Debug/ClassDll.lib")
int main(){
	CMath math;
	int add=math.Add(1,2);
	int sub=math.Sub(2,3);
	cout<<"sum="<<add<<",sub="<<sub<<endl;
	getchar();
	return 0;
}

26.线程

26.1.线程基础

26.2.创建线程

#include <Windows.h>
#include <stdio.h>

DWORD WINAPI TestProc(  LPVOID lpParameter){
	char* pszText=(char*)lpParameter;
	while(1){
		printf("%s\n",pszText);
		Sleep(1000);
	}
	return 0;

}

DWORD WINAPI TestProc2(LPVOID lpParameter){
	char* pszText=(char*)lpParameter;
	while(1){
		printf("%s\n",pszText);
		Sleep(1000);
	}
	return 0;
}
int main(){
	DWORD nId=0;
	char* pszText="********";
	HANDLE hThread=CreateThread(NULL,0,TestProc,pszText,0,&nId);
	char* pszText2="--------";
	HANDLE hThread2=CreateThread(NULL,0,TestProc2,pszText2,0,&nId);
	getchar();
	return 0;
}

26.3.线程挂起和毁

26.4.线程相关操作

27、线程同步

27.1. 原子锁

27.1.1. 原子锁解决的问题

27.1.2.使用原子锁

InterlockedIncrement
InterlockedDecrement
InterlockedCompareExchange
InterlockedExchange

27.1.3.原子锁代码示例

#include <Windows.h>
#include <stdio.h>
long g_value=0;
DWORD WINAPI TestProc1(LPVOID pParam){
	for(int i=0;i<100000;i++){
		//g_value++;
		InterlockedIncrement(&g_value);
	}
	return 0;
}

DWORD WINAPI TestProc2(LPVOID pParam){
	for(int i=0;i<100000;i++){
		//g_value++;
		InterlockedIncrement(&g_value);
	}
	return 0;
}
int main(){
	DWORD nID=0;
	HANDLE hThread[2];
	hThread[0]=CreateThread(NULL,0,TestProc1,NULL,0,&nID);
	hThread[1]=CreateThread(NULL,0,TestProc2,NULL,0,&nID);
	WaitForMultipleObjects(2,hThread,TRUE,INFINITE);
	printf("%d\n",g_value);
	return 0;
}

27.2. 互斥

27.2.1. 互斥解决的问题

27.2.2. 互斥的使用

BOOL ReleaseMutex(  
	HANDLE hMutex   // handle to mutex
);
BOOL CloseHandle( 
	 HANDLE hObject   // handle to object
);

27.2.3. 互斥代码示例

#include <Windows.h>
#include <stdio.h>
HANDLE g_hMutex=0;//接收互斥句柄
DWORD WINAPI TestProc(  LPVOID lpParameter){
	char* pszText=(char*)lpParameter;
	while(1){
		WaitForSingleObject(g_hMutex,INFINITE);//等候互斥有信号
		for(int i=0;i<strlen(pszText);i++){
			printf("%c",pszText[i]);
			Sleep(125);
		}
		printf("\n");
		ReleaseMutex(g_hMutex);//释放互斥
	}
	return 0;

}

DWORD WINAPI TestProc2(LPVOID lpParameter){
	char* pszText=(char*)lpParameter;
	while(1){
		WaitForSingleObject(g_hMutex,INFINITE);//等候互斥有信号
		for(int i=0;i<strlen(pszText);i++){
			printf("%c",pszText[i]);
			Sleep(125);
		}
		printf("\n");
		ReleaseMutex(g_hMutex);//释放互斥
	}
	return 0;
}
int main(){
	g_hMutex=CreateMutex(NULL,FALSE,NULL);//主线程不拥有互斥,我们要子线程与子线程互斥	
	DWORD nId=0;
	char* pszText="********";
	HANDLE hThread=CreateThread(NULL,0,TestProc,pszText,0,&nId);//线程创建成功,立刻执行
	
	char* pszText2="--------";
	HANDLE hThread2=CreateThread(NULL,0,TestProc2,pszText2,0,&nId);//线程创建成功,立刻执行

	
	getchar();
	CloseHandle(g_hMutex);
	return 0;
}

27.2.4. 原子锁与互斥

27.3. 事件

27.3.1. 事件解决的问题

27.3.2. 事件的使用

BOOL SetEvent(  
		HANDLE hEvent   // handle to event
);
BOOL ResetEvent(  
	HANDLE hEvent   // handle to event
);

27.3.3. 事件的死锁

27.3.4. 事件的代码示例

#include <Windows.h>
#include <stdio.h>
HANDLE g_hEvent=0;
DWORD WINAPI PrintProc(LPVOID pParam){
	while(1){
		WaitForSingleObject(g_hEvent,INFINITE);//等待事件有信号
		ResetEvent(g_hEvent);
		printf("*********\n");
		
	}
	return 0;
}

DWORD WINAPI CtrlProc(LPVOID pParam){
	while(1){
		Sleep(1000);
		SetEvent(g_hEvent);
	}
	return 0;
}

int main(){
	g_hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);//初始事件句柄无信号,需手动复位
	DWORD nID=0;
	HANDLE hThread[2]={0};
	hThread[0]=CreateThread(NULL,0,PrintProc,NULL,0,&nID);
	hThread[1]=CreateThread(NULL,0,CtrlProc,NULL,0,&nID);
	WaitForMultipleObjects(2,hThread,TRUE,INFINITE);
	CloseHandle(g_hEvent);
	return 0;
}

27.4. 信号量

27.4. 1.信号量解决的问题

27.4. 2.信号量的使用

BOOL ReleaseSemaphore(  
		  HANDLE hSemaphore,       // handle to semaphore信号量句柄
		  LONG lReleaseCount,      // count increment amount释放数量
		  LPLONG lpPreviousCount   // previous count释放前原来信号量的数量,可以为NULL
  );

27.4. 3.信号量代码示例

#include <Windows.h>
#include <stdio.h>
HANDLE g_hSema=0;
DWORD WINAPI TestProc(LPVOID pParam){
	while(1){
		WaitForSingleObject(g_hSema,INFINITE);
		printf("***********\n");
	}
}

int main(){
	g_hSema=CreateSemaphore(NULL,3,10,NULL);
	DWORD nID=0;
	HANDLE hThread=CreateThread(NULL,0,TestProc,NULL,0,&nID);
	getchar();
	ReleaseSemaphore(g_hSema,5,NULL);//不想接收剩余的信号量,可以设为NULL
	WaitForSingleObject(hThread,INFINITE);
	CloseHandle(g_hSema);
	return 0;
}

标签:NULL,wc,入门,int,hWnd,WM,Win32,窗口,放弃
来源: https://blog.csdn.net/chuhe163/article/details/122028035