1.如图,实现功能:
- Hello World!字符串跟随鼠标移动
- 鼠标左击Hello World!颜色为红色
- 鼠标右击Hello World!颜色为蓝色
鼠标滚轮滚动改变Hello World!颜色的RGB中的G值
2.实现工具:
- vs2013
3.实现步骤:
新建一个win32项目
如图,看到HelloWorldGame.cpp中
_tWinMain()的函数是程序入口函数,
WndProc()是处理主窗口的所有消息,
About()是显示关于信息
这样就搭建好了win32框架
接下来开始使用GDI图形编程
在WndProc函数中找到case WM_PAINT,在注释中可以看出,WM_PAINT表示绘制消息,我们就是在此
进行绘制操作,我们加入以下代码
TextOut(hdc,0,0,L"Hello World!",12);
/*
参数解释:
hdc 待输出的设备
0 坐标x
0 坐标y
L"Hello World!" L表示将ANSI字符转换为unicode 以便支持中文,Hello World!表示要打印的字符串
12 表示要输出的字符数
*/
F5运行
效果如图
好,接下来我们来添加颜色
在变量声明区域加入以下代码
int r = 125;
int g = 125;
int b = 125;
COLORREF color = RGB(r, g, b);
//定义一个颜色索引color
并在TextOut函数前加入
SetTextColor(hdc, color);//设置文本的颜色
F5运行
如图
好的继续,我们来增加一些互动性,添加更多的消息处理
在WndProc函数中
添加以下代码
case WM_LBUTTONDOWN://鼠标左击消息
color = RGB(255, 0, 0);
break;
case WM_RBUTTONDOWN://鼠标右击消息
color = RGB(0, 0, 255);
break;
F5运行一下看看,哈哈O(∩_∩)O哈!是不是发现没效果!
对!没效果是对的,为什么呢?
因为没有及时发出重新绘制消息
case WM_LBUTTONDOWN://鼠标左击消息
color = RGB(255, 0, 0);
InvalidateRect(hWnd, NULL, TRUE);
break;
case WM_RBUTTONDOWN://鼠标右击消息
color = RGB(0, 0, 255);
InvalidateRect(hWnd, NULL, TRUE);
这样就行了
/*
InvalidateRect参数
hWnd 窗口句柄
NULL 设置矩形
TRUE 设置重画
*/
F5运行
好的,我们实现了鼠标左右击颜色变化
接下来,我们加入鼠标移动消息处理,让Hello World!跟着鼠标移动
首先在声明区声明
WCHAR str[64];
int x = 200, y = 150;
然后在WndProc中加入
case WM_MOUSEMOVE:
x = LOWORD(lParam);//得到x坐标
y = HIWORD(lParam);//得到y坐标
InvalidateRect(hWnd, NULL, TRUE);//发出重绘消息
break;
F5运行
好的,接下来添加鼠标滚轮消息
case WM_MOUSEWHEEL:
//得到鼠标滚轮的参数
int zDelta = (short)HIWORD(wParam);
if (zDelta > 0) //正值向前
{
if (g<255)
g += 1;
}
else //负值向后
{
if (g>0)
g--;
}
color = RGB(0, g, 122);
InvalidateRect(hWnd, NULL, TRUE);
break;
编译运行试试,你发现了什么,haha,编译不同过
因为在case 中定义变量需要用括号把整个部分包含起来才行
case WM_MOUSEWHEEL:
{
//得到鼠标滚轮的参数
int zDelta = (short)HIWORD(wParam);
if (zDelta > 0) //正值向前
{
if (g<255)
g += 1;
}
else //负值向后
{
if (g>0)
g--;
}
color = RGB(0, g, 122);
InvalidateRect(hWnd, NULL, TRUE);
}
break;
我们再添加显示x,y,r,g,b值
定义
int r = 125;
int g = 125;
int b = 125;
COLORREF color = RGB(r, g, b);
WCHAR infor[64];
int x = 200, y = 150;
在case WM_PAINT:中
swprintf_s(infor, L"r:%d,g:%d,b:%d
x=%d,y=%d",r,g,b, x, y);//格式化字符串
TextOut(hdc, x, y - 100, infor, wcslen(infor));
F5运行一下
就得到了实现的效果
下面给出 HelloWorldGame.cpp的代码
1 // HelloWorldGame.cpp : Defines the entry point for the application. 2 // 3 4 #include "stdafx.h" 5 #include "HelloWorldGame.h" 6 7 #define MAX_LOADSTRING 100 8 9 // Global Variables: 10 HINSTANCE hInst; // current instance 11 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text 12 TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name 13 14 // 15 int r = 125; 16 int g = 125; 17 int b = 125; 18 COLORREF color = RGB(r, g, b); 19 WCHAR infor[64]; 20 int x = 200, y = 150; 21 // 22 // Forward declarations of functions included in this code module: 23 ATOM MyRegisterClass(HINSTANCE hInstance); 24 BOOL InitInstance(HINSTANCE, int); 25 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 26 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); 27 28 int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, 29 _In_opt_ HINSTANCE hPrevInstance, 30 _In_ LPTSTR lpCmdLine, 31 _In_ int nCmdShow) 32 { 33 UNREFERENCED_PARAMETER(hPrevInstance); 34 UNREFERENCED_PARAMETER(lpCmdLine); 35 36 // TODO: Place code here. 37 MSG msg; 38 HACCEL hAccelTable; 39 40 // Initialize global strings 41 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 42 LoadString(hInstance, IDC_HELLOWORLDGAME, szWindowClass, MAX_LOADSTRING); 43 MyRegisterClass(hInstance); 44 45 // Perform application initialization: 46 if (!InitInstance(hInstance, nCmdShow)) 47 { 48 return FALSE; 49 } 50 51 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HELLOWORLDGAME)); 52 53 // Main message loop: 54 while (GetMessage(&msg, NULL, 0, 0)) 55 { 56 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 57 { 58 TranslateMessage(&msg); 59 DispatchMessage(&msg); 60 } 61 } 62 63 return (int)msg.wParam; 64 } 65 66 67 68 // 69 // FUNCTION: MyRegisterClass() 70 // 71 // PURPOSE: Registers the window class. 72 // 73 ATOM MyRegisterClass(HINSTANCE hInstance) 74 { 75 WNDCLASSEX wcex; 76 77 wcex.cbSize = sizeof(WNDCLASSEX); 78 79 wcex.style = CS_HREDRAW | CS_VREDRAW; 80 wcex.lpfnWndProc = WndProc; 81 wcex.cbClsExtra = 0; 82 wcex.cbWndExtra = 0; 83 wcex.hInstance = hInstance; 84 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELLOWORLDGAME)); 85 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 86 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 87 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HELLOWORLDGAME); 88 wcex.lpszClassName = szWindowClass; 89 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 90 91 return RegisterClassEx(&wcex); 92 } 93 94 // 95 // FUNCTION: InitInstance(HINSTANCE, int) 96 // 97 // PURPOSE: Saves instance handle and creates main window 98 // 99 // COMMENTS: 100 // 101 // In this function, we save the instance handle in a global variable and 102 // create and display the main program window. 103 // 104 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 105 { 106 HWND hWnd; 107 108 hInst = hInstance; // Store instance handle in our global variable 109 110 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 111 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 112 113 if (!hWnd) 114 { 115 return FALSE; 116 } 117 118 ShowWindow(hWnd, nCmdShow); 119 UpdateWindow(hWnd); 120 121 return TRUE; 122 } 123 124 // 125 // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) 126 // 127 // PURPOSE: Processes messages for the main window. 128 // 129 // WM_COMMAND - process the application menu 130 // WM_PAINT - Paint the main window 131 // WM_DESTROY - post a quit message and return 132 // 133 // 134 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 135 { 136 int wmId, wmEvent; 137 PAINTSTRUCT ps; 138 HDC hdc; 139 140 switch (message) 141 { 142 case WM_COMMAND: 143 wmId = LOWORD(wParam); 144 wmEvent = HIWORD(wParam); 145 // Parse the menu selections: 146 switch (wmId) 147 { 148 case IDM_ABOUT: 149 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 150 break; 151 case IDM_EXIT: 152 DestroyWindow(hWnd); 153 break; 154 default: 155 return DefWindowProc(hWnd, message, wParam, lParam); 156 } 157 break; 158 case WM_LBUTTONDOWN://鼠标左击消息 159 color = RGB(255, 0, 0); 160 InvalidateRect(hWnd, NULL, TRUE); 161 break; 162 case WM_RBUTTONDOWN://鼠标右击消息 163 color = RGB(0, 0, 255); 164 InvalidateRect(hWnd, NULL, TRUE); 165 break; 166 case WM_MOUSEMOVE: 167 x = LOWORD(lParam);//得到x坐标 168 y = HIWORD(lParam);//得到y坐标 169 InvalidateRect(hWnd, NULL, TRUE);//发出重绘消息 170 break; 171 case WM_MOUSEWHEEL: 172 { 173 //得到鼠标滚轮的参数 174 int zDelta = (short)HIWORD(wParam); 175 if (zDelta > 0) //正值向前 176 { 177 if (g<255) 178 g += 1; 179 180 } 181 else //负值向后 182 { 183 if (g>0) 184 g--; 185 } 186 color = RGB(0, g, 122); 187 InvalidateRect(hWnd, NULL, TRUE); 188 } 189 break; 190 191 case WM_PAINT: 192 hdc = BeginPaint(hWnd, &ps); 193 // TODO: Add any drawing code here... 194 SetTextColor(hdc, color); 195 TextOut(hdc, x, y, L"Hello World!", 12); 196 swprintf_s(infor, L"r:%d,g:%d,b:%d x=%d,y=%d",r,g,b, x, y);//格式化字符串 197 TextOut(hdc, x, y - 100, infor, wcslen(infor)); 198 EndPaint(hWnd, &ps); 199 break; 200 case WM_DESTROY: 201 PostQuitMessage(0); 202 break; 203 default: 204 return DefWindowProc(hWnd, message, wParam, lParam); 205 } 206 return 0; 207 } 208 209 // Message handler for about box. 210 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 211 { 212 UNREFERENCED_PARAMETER(lParam); 213 switch (message) 214 { 215 case WM_INITDIALOG: 216 return (INT_PTR)TRUE; 217 218 case WM_COMMAND: 219 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 220 { 221 EndDialog(hDlg, LOWORD(wParam)); 222 return (INT_PTR)TRUE; 223 } 224 break; 225 } 226 return (INT_PTR)FALSE; 227 }