此系列在学习CSDN大神"浅墨"(http://blog.csdn.net/poem_qianmo)的《逐梦旅程》过程中展开。
这本书前半部分讲GDI,后半部分讲DirectX,讲述风格适合初学者,有基础的也可以作为参考。
下面开始我的第一个示例,一个最基本的Windows Application,涉及到窗口、消息/事件等基本内容。
以下是运行中某时刻的截图:
这是编译后的程序以及声音资源
图标是从Dota2搬过来的,声音也是Dota英雄的声音资源
程序启动时刻会播放声音 “FirstBlood"
在窗口内单击鼠标左键会在点击位置描绘* 并播放声音"God Like It"
在窗口内单击鼠标右键会在点击位置描绘x 并播放声音 "Holy Shit"
按下x(或X)键则弹出图示的消息框
按下Esc或者Alt+F4组合键关闭窗口并退出程序
以下是主要业务代码(不包含Resource文件)
#include <windows.h>
#pragma comment(lib,"winmm.lib")
#include "resource.h"
#define SCREEN_WIDTH ( GetSystemMetrics(SM_CXSCREEN) )
#define SCREEN_HEIGHT ( GetSystemMetrics(SM_CYSCREEN) )
#define WINDOW_LEFT ( SCREEN_WIDTH/10 )
#define WINDOW_TOP ( SCREEN_HEIGHT/10 )
#define WINDOW_WIDTH ( SCREEN_WIDTH*4/5 )
#define WINDOW_HEIGHT ( SCREEN_HEIGHT*4/5 )
#define WINDOW_TITLE TEXT("First Blood") //窗口标题
#define WINDOW_CLASS TEXT("MainWindow")
LPCSTR lpszIconFile = TEXT("steam_dota.ico");
LPCSTR lpszSounS = TEXT("S_Dota_FirstBlood.wav");
LPCSTR lpszSounL = TEXT("L_Dota_GodLikeIt.wav");
LPCSTR lpszSounR = TEXT("R_Dota_HolyShit.wav");
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); //窗口过程函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX wndClass = { 0 };
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = WINDOW_CLASS;
if (!RegisterClassEx(&wndClass))
{
return -1;
}
HWND hwnd = CreateWindow(WINDOW_CLASS, WINDOW_TITLE,
WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
MoveWindow(hwnd, WINDOW_LEFT, WINDOW_TOP, WINDOW_WIDTH, WINDOW_HEIGHT, true);
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// Render Loop
}
}
UnregisterClass(WINDOW_CLASS, wndClass.hInstance);
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC = NULL;
switch (message)
{
case WM_CREATE:
PlaySound(lpszSounS, NULL, SND_FILENAME|SND_ASYNC);
break;
case WM_PAINT:
ValidateRect(hwnd, NULL);
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE) // 如果被按下的键是ESC
DestroyWindow(hwnd);
break;
case WM_LBUTTONDOWN:
hDC = GetDC(hwnd);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(0, 0, 255));
TextOut(hDC, LOWORD(lParam), HIWORD(lParam), TEXT("*"), 1);
PlaySound(lpszSounL, NULL, SND_FILENAME | SND_ASYNC);
DeleteDC(hDC);
break;
case WM_RBUTTONDOWN:
hDC = GetDC(hwnd);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(255, 0, 0));
TextOut(hDC, LOWORD(lParam), HIWORD(lParam), TEXT("x"), 1);
PlaySound(lpszSounR, NULL, SND_FILENAME | SND_ASYNC);
DeleteDC(hDC);
break;
case WM_CHAR:
if (LOWORD(wParam) == 'x')
MessageBox(hwnd, TEXT("你按下了X键"), TEXT("提示"), MB_OK | MB_ICONINFORMATION);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0; //正常退出
}
因为这是相对高阶的内容,一些细节的解释将放在独成系列的几个单独的博文当中
先暂时记录到这里,稍后抽空持续更新
本文原创,原始链接