[toc]

音频

c/c++在控制台程序中调用api播放音频

方法一

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <windows.h>
#include "mmsystem.h"//导入声音头文件

#pragma comment(lib,"winmm.lib")//导入声音头文件库

int main(int argc, const char* argv[])
{
mciSendString(L"OPEN D:\\desktop\\video.mp3 ALIAS MUSIC", NULL, 0, 0);
mciSendString(L"PLAY MUSIC FROM 0", NULL, 0, NULL);

LPWSTR wavLength[64];
long iWavLength = 0;
mciSendString(L"status MUSIC length", (LPWSTR)wavLength, 64, NULL);
MessageBox(0, (LPWSTR)wavLength, L"title", 0);
mciSendString(L"CLOSE MUSIC", NULL, 0, NULL);

return 0;
}

方法二

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <windows.h>
#include "mmsystem.h"//导入声音头文件

#pragma comment(lib,"winmm.lib")//导入声音头文件库


int main(int argc, const char* argv[])
{

//播放文件声音
//PlaySound(L"D:\\desktop\\video.wav", NULL, SND_FILENAME | SND_ASYNC);
//循环播放文件声音
PlaySound(L"C:\\SOUNDS\\BELLS.WAV", NULL, SND_LOOP | SND_ASYNC | SND_FILENAME);
MessageBox(0, L"1", L"title", 0);
//异步播放文件声音
//PlaySound("C:\\SOUNDS\\BELLS.WAV", NULL, SND_SYNC);
//播放系统声音
//PlaySound(L"MouseClick", NULL, SND_SYNC);
return 0;
}

Debug

Output debug information in win32 application

Debug.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <windows.h>
#include <tchar.h>
#include <string>

int APIENTRY WinMain(
HINSTANCE hinstance, // handle to current instance
HINSTANCE hinstPrev, // handle to previous instance
LPSTR lpCmdLine, // address of command-line string
int nCmdShow) // show-window type
{

//整数转为字符print debug information
int num = 11;
wchar_t string[100];
swprintf(string, 100, L"%d\n", num);
OutputDebugString(string);
std::wstring value = std::to_wstring(num) + L"\n";
OutputDebugString(value.c_str());
const wchar_t* putout = L"dddddddd\n";
OutputDebugString(putout);
OutputDebugString(L"tdfgvgufvghaiukhngk\n");

//call console
FILE* fp;
AllocConsole();
freopen_s(&fp, "CONIN$", "r", stdin);
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);
wprintf(L"console");
system("pause");

return 0;

}

去除控制台

使用预处理命令

在头文件下加上一句预处理命令:

1
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址

完整程序

1
2
3
4
5
6
7
#include<windows.h>
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址
int main()
{
MessageBox(NULL,"Hello","Notice",NULL);
return 0;
}

结果:在编译器下运行时仍会出现黑框,但直接运行编译好的exe程序就不会显示黑框了

C\C++控制台程序隐藏方法总结

通过main函数画窗口程序

1从 main() 函数开始写一个 Windows GUI 程序。 WinMain() 函数的参数通过相应的 API 得到。

1
2
3
4
5
6
7
8
9
#include <windows.h>

int main(int argc, char *argv[]){
HINSTANCE hInst = GetModuleHandle(NULL);
HINSTANCE prev = NULL;
LPWSTR cmdline = GetCommandLineW();
int show;
return 0;
}

用 GCC 进行编译的命令如下

1
gcc -mwindows -o FileName.exe FileName.c

2完善GUI创建窗口

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <windows.h>
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int main(int argc, char* argv[]) {
HINSTANCE hInstance = GetModuleHandle(NULL);
HINSTANCE hPrevInstance = NULL;
LPSTR lpCmdLine = GetCommandLineA();
int nShowCmd;

WNDCLASSEXW wc = { };
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
LPCWSTR ClassName= L"Sample Window Class";
wc.lpszClassName = ClassName;
/*
1.注册 RegisterClassEx
2.创建窗口 CreateWindowEx
3.显示窗口 ShowWindow
4.进入消息循环 GetMessage
*/
RegisterClassExW(&wc);

HWND hwnd = CreateWindowExW(
0, // Optional window styles.
wc.lpszClassName, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
100,
100,
800,
600,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);

ShowWindow(hwnd, SW_NORMAL);

MSG msg = { };
while (GetMessage(&msg, hwnd, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}


}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

switch (uMsg)
{

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

return 0;
}


通过在main函数里调用WinMain函数实现GUI程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <windows.h>

LRESULT CALLBACK WindowProcedure(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam
) {
switch (message) {
case WM_CREATE:
return 0;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_COMMAND:
case WM_APP:
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

int RegisterWindowClass(HINSTANCE hInstance, const wchar_t* className) {

WNDCLASSEXW wclx;
memset(&wclx, 0, sizeof(WNDCLASSEX));

wclx.cbSize = sizeof(WNDCLASSEX);
wclx.hInstance = hInstance;
wclx.lpszClassName = className;
wclx.lpfnWndProc = WindowProcedure; /* Message Callback */
wclx.style = 0;

wclx.hCursor = LoadCursor(NULL, IDC_ARROW);
wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wclx.lpszMenuName = NULL;
wclx.cbClsExtra = 0; /* Extra bytes after the window class */
wclx.cbWndExtra = 0; /* Extra structure or window instance */

// wclx.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ICO1));
// wclx.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(ICO1));


if (!RegisterClassExW(&wclx)) {
MessageBoxW(NULL,
L"can not create window class",
L"aha",
MB_ICONERROR | MB_OK | MB_TOPMOST);
return 0;
}
return 1;
}

int WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
) {

/* 1. Register Window Class */
const wchar_t* szClassName = L"Mingw Windows Demo";

RegisterWindowClass(hInstance, szClassName);

/* 2. Create Window */

HWND hWnd = CreateWindowExW(
0, /* Extended possibilites for variation */
szClassName, /* Classname */
szClassName, /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);

ShowWindow(hWnd, nCmdShow);
/* 3. Message Loop */

MSG message;
while (GetMessage(&message, NULL, 0, 0)) {
TranslateMessage(&message);
DispatchMessage(&message);
}

/* 4. Clean up */
UnregisterClassW(szClassName, hInstance);

return message.wParam;
}

int main(int argc, char* argv[]) {
/* 0. Prepare WinMain Parameters */
HINSTANCE hInstance = GetModuleHandle(NULL);
HINSTANCE hPrevInstance = NULL;
LPSTR lpCmdLine = GetCommandLineA();
int nCmdShow = SW_SHOW;

return WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
};

编译命令

-mwindows表明是编译图形窗口程序

1
gcc -mwindows console.cpp

保留控制台的编译命令

1
gcc -mconsole console.cpp

控制台打印多语言

方法一setlocalewprintf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <locale.h>

int main(int argc,char *argv[])
{
/*
_wsetlocale(LC_ALL, L"chs"); //chs 表示中文 方法一
setlocale(LC_ALL, "chs"); //chs 表示中文 方法二
*/

setlocale(LC_ALL, ""); // c语言函数,本地化语言设置为中文,否则中文乱码

const char* p1 = "english 简体中文"; //普通字符串 - 多字节字符串
const wchar_t* p2 = L"english 简体中文"; //unicode字符串 - 字符串有修饰符 L
printf("p1 :%s \n", p1);
wprintf(L"p2 :%s \n", p2);
printf("p2 :%ls \n", p2);
return 0;
}

方法二: WriteConsoleW

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <windows.h>

int main(int argc,char *argv[])
{
AllocConsole();
HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsoleW(consoleHandle, L"English ąęėšų 简体中文\n", 19, NULL, NULL);

//函数原型
BOOL WINAPI WriteConsole(
_In_ HANDLE hConsoleOutput,
_In_ const VOID * lpBuffer,
_In_ DWORD nNumberOfCharsToWrite,
_Out_opt_ LPDWORD lpNumberOfCharsWritten,
_Reserved_ LPVOID lpReserved
);
return 0;
}

方法三:Write Console

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <windows.h>
#include <tchar.h>

int main(int argc,char *argv[])
{
HANDLE hStdout;
DWORD dwChars;
TCHAR buf[] = _T("您好,世界,Helloworld\n");
int len = lstrlen(buf);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdout == INVALID_HANDLE_VALUE)
{
return -1;
}
WriteConsole(hStdout, buf, len, &dwChars, NULL);
return 0;
}

键盘消息与鼠标消息

键盘消息

1
2
3
4
5
6
7
8
9
case WM_KEYDOWN:
switch (wParam)
{
case VK_UP:
printf("up\n");
MessageBoxEx(hwnd, L"text", L"Caption", NULL, NULL);
break;
}
break;

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <windows.h>
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int main(int argc, char* argv[]) {
HINSTANCE hInstance = GetModuleHandle(NULL);
HINSTANCE hPrevInstance = NULL;
LPSTR lpCmdLine = GetCommandLineA();
int nShowCmd;

WNDCLASSEXW wc = { };
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
LPCWSTR ClassName = L"Sample Window Class";
wc.lpszClassName = ClassName;
/*
1.注册 RegisterClassEx
2.创建窗口 CreateWindowEx
3.显示窗口 ShowWindow
4.进入消息循环 GetMessage
*/
RegisterClassExW(&wc);

HWND hwnd = CreateWindowExW(
0, // Optional window styles.
wc.lpszClassName, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
100,
100,
800,
600,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);

ShowWindow(hwnd, SW_NORMAL);

MSG msg = { };
while (GetMessage(&msg, hwnd, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}


}
#include <stdio.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

switch (uMsg)
{
case WM_KEYDOWN:
switch (wParam)
{
case VK_UP:
printf("up\n");
MessageBoxEx(hwnd, L"text", L"Caption", NULL, NULL);
break;
}
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

return 0;
}

键盘钩子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <windows.h>
#include <stdio.h>


HHOOK g_Hook;
LRESULT CALLBACK KeyboardProc(int code, WPARAM w, LPARAM l)
{
KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)l;
// wParam和lParam参数包含关于键盘消息的信息。
// WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP.
if (code == HC_ACTION)
{
switch (p->vkCode)
{
case VK_UP:
{
if (w == WM_KEYDOWN)
{
// 如果大于0,则键按下;反之小写
printf("摁下按键\n");
//MessageBoxEx(NULL, L"text", L"Caption", NULL, NULL);

}
else if (w == WM_KEYUP)
{
printf("抬起按键\n");
}
}
}
}
return CallNextHookEx(g_Hook, code, w, l);
}
int main()
{

g_Hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, GetModuleHandle(NULL), 0);

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

UnhookWindowsHookEx(g_Hook);
return msg.wParam;
}

全局热键

控制台程序全局热键

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <windows.h>
#include <stdio.h>


int _cdecl wmain(
int argc,
TCHAR* argv[])
{
// Register the hot key with CTRL+ALT+F as the key combination

if (RegisterHotKey(
NULL,
1,
MOD_ALT | MOD_NOREPEAT,
0x42)) //0x42 is 'b'
{
wprintf(TEXT("Hotkey 'ALT+b' registered, using MOD_NOREPEAT flag\n"));
}
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
if (msg.message == WM_HOTKEY)
{
if (msg.wParam == 1)
{

wprintf(TEXT("WM_HOTKEY received\n"));
}
}
}

return 0;
}

窗口程序全局热键

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Include the necessary header files
#include <windows.h>
//#pragma comment( linker, "/subsystem:\"windows\" /entry:\"WinMainCRTStartup\"" )
// Define the global variables
HINSTANCE hInst; // The application instance handle
HWND hWnd; // The main window handle
UINT uHotKeyId; // The hot key identifier

// Declare the window procedure function
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

// The entry point of the application
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Initialize the global variables
hInst = hInstance;
uHotKeyId = 100; // Any value between 0x0000 and 0xBFFF

// Define the window class structure
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(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = TEXT("HotKeyDemo");
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

// Register the window class
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL, TEXT("Failed to register the window class."), TEXT("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}

// Create the main window
hWnd = CreateWindow(TEXT("HotKeyDemo"), TEXT("Hot Key Demo"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
MessageBox(NULL, TEXT("Failed to create the main window."), TEXT("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}

// Show and update the main window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

// Register the hot key with CTRL+ALT+F as the key combination
if (!RegisterHotKey(hWnd, uHotKeyId, MOD_ALT, 0x46)) // 0x46 is the virtual key code for F
{
MessageBox(NULL, TEXT("Failed to register the hot key."), TEXT("Error"), MB_OK | MB_ICONERROR);
return FALSE;
}

// Enter the message loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (int)msg.wParam;
}

// Define the window procedure function
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_HOTKEY:
// Check if the message is from the registered hot key
if (wParam == uHotKeyId)
{
// Do something when the hot key is pressed
MessageBox(NULL, TEXT("You pressed CTRL+ALT+F!"), TEXT("Hot Key"), MB_OK | MB_ICONINFORMATION);
}
break;

case WM_DESTROY:
// Unregister the hot key before exiting
UnregisterHotKey(hWnd, uHotKeyId);
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}

return 0;
}

MyKeyMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  
#include<windows.h>
int MyKeyMessage()
{
while (true)
{
Sleep(200);
if (GetAsyncKeyState(VK_F8))
{
MessageBox(NULL, L"F8", L"", MB_ICONEXCLAMATION);
while (true)
{
Sleep(600);
//keybd_event(VK_SPACE, 0x20, KEYEVENTF_EXTENDEDKEY | 0, 0);
if (GetAsyncKeyState(VK_ESCAPE) && GetAsyncKeyState(VK_F9))
{
MessageBox(NULL, L"ESCAPE", L"", MB_ICONEXCLAMATION);
goto start; //start hating
}

if (GetAsyncKeyState(VK_F9))
{
MessageBox(NULL, L"F9", L"", MB_ICONEXCLAMATION);
return 0;
}
}
}

}
start:
return 0;
}
int main ()
{
MyKeyMessage();
return 0;
}

HookKeyBoard

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <windows.h>
#include <iostream>

using namespace std;

HHOOK keybdhook;
LRESULT CALLBACK KeyboardHook(int nCode, WPARAM wParam, LPARAM lParam); // declaration of the callback
void HookKeyBoard()
{

keybdhook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHook, GetModuleHandle(0), 0);
if (keybdhook == 0)
{
cout << "Fail to create hook" << endl;
}

MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}


}

LRESULT CALLBACK KeyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT* key;
if (wParam == WM_KEYDOWN)
{
key = (KBDLLHOOKSTRUCT*)lParam;

//hotkey example
if (key->vkCode == VkKeyScan('a'))
{
cout << "You pressed 'a'" << endl;
}
if (key->vkCode == VK_F1)
{
cout << "You pressed the F1 key" << endl;
}
}
return CallNextHookEx(keybdhook, nCode, wParam, lParam);
}
int main ()
{
HookKeyBoard();
return 0;
}

GetMousePosition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <windows.h>
#include <iostream>
void GetMousePosition()
{
while (true)
{
POINT mousePos;
GetCursorPos(&mousePos);
std::cout << "(" << mousePos.x << "," << mousePos.y << ")";
Sleep(20);
system("cls");
}
}
int main ()
{
GetMousePosition();
return 0;
}

console key state

C语言控制台窗口图形界面编程(七):键盘事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>  
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#define true 1
#define false 0

int main()
{
HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); //获得标准输入设备句柄
INPUT_RECORD keyrec; //定义输入事件结构体
DWORD res; //定义返回记录
for (;;)
{
ReadConsoleInput(handle_in, &keyrec, 1, &res); //读取输入事件
if (keyrec.EventType == KEY_EVENT) //如果当前事件是键盘事件
{
if (keyrec.Event.KeyEvent.wVirtualKeyCode == 'A'
&& keyrec.Event.KeyEvent.bKeyDown == true) //当按下字母A键时
{
if (keyrec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) //Shift键为按下状态
{
printf("Shift+");
}
if (keyrec.Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON) //大写锁定为打开状态
{
printf("A ");
}
else //大写锁定关闭状态
{
printf("a ");
}
}
}
}
return 0;
}

使用GDI绘图

使用GID画一条线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <windows.h>

// 用于注册的窗口类名
const char g_szClassName[] = "myWindowClass";

void Paint(HWND hwnd)
{
// paint struct 绘图结构体,存储目标窗口可以绘图的客户端区域(client area)
PAINTSTRUCT ps;
HDC hdc; // DC(可画图的内存对象) 的句柄
HPEN hpen; // 画笔

// 通过窗口句柄获取该窗口的 DC
hdc = BeginPaint(hwnd, &ps);
// 创建画笔
hpen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
// DC 选择画笔
SelectObject(hdc, hpen);
// (画笔)从初始点移动到 50,50
MoveToEx(hdc, 50, 50, NULL);
// (画笔)从初始点画线到 100,100
LineTo(hdc, 150, 100);

EndPaint(hwnd, &ps);
}
/*
* 第四步,窗口过程
*/
LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
// 窗口绘制消息

case WM_PAINT:

// 我们只需要在这里调用我们的 GDI 绘制函数就可以,其他地方可以先无视
Paint(hwnd); // 调用我们的 GDI 绘制函数

break;
// 窗口关闭消息

case WM_CLOSE:
DestroyWindow(hwnd);
break;
// 窗口销毁消息
case WM_DESTROY:
PostQuitMessage(0); // 发送离开消息给系统
break;
// 其他消息
default:
// pass 给系统,咱不管
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}


//第一步,注册窗口类

void RegisterMyWindow(HINSTANCE hInstance)
{
WNDCLASSEX wc;

// 1)配置窗口属性
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = MyWindowProc; // 设置第四步的窗口过程回调函数
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

// 2)注册
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, TEXT("窗口注册失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK);
exit(0); // 进程退出
}
}


//第二步,创建窗口

HWND CreateMyWindow(HINSTANCE hInstance, int nCmdShow)
{
HWND hwnd;
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
TEXT("我的窗口名称"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, // 出现坐标 x,y 默认分配 窗口宽 400 高 300
NULL, NULL, hInstance, NULL);

if (hwnd == NULL)
{
MessageBox(NULL, TEXT("窗口创建失败!"), TEXT("错误"), MB_ICONEXCLAMATION | MB_OK);
exit(0); // 进程退出
}

// 显示窗口
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

return hwnd;
}


// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;
MSG Msg;

// 第一步,注册窗口类
RegisterMyWindow(hInstance);
// 第二步:创建窗口
hwnd = CreateMyWindow(hInstance, nCmdShow);
// 第三步:消息循环
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}

使用win32api加载图片并添加鼠标事件与键盘事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

#include <windows.h>

#pragma comment(lib,"Msimg32.lib")

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lParam);


//hInstance 实例句柄,每一个应用程序都是有一个应用程序的实例句柄 (唯一的)
//lpCmdLine 命令行的参数
//nShowCmd 用来指定窗口如何显示,最大化,还是最小化
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {

//MessageBox(NULL, L"Hello 你好 windows", L"这个是标题", 0);//msdn

//1,设计窗口
WNDCLASSEX wndClass = {};
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.lpszClassName = L"myclassname";
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;

//2,注册窗口
if (RegisterClassEx(&wndClass) == false) {
return -1;
}

//3,创建窗口 hwnd是我们创建出来的一个窗口句柄 就是这个窗口的身份证号
HWND hwnd = CreateWindow(L"myclassname", L"创建第一个窗口", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 480, 852, NULL, NULL, hInstance, NULL);

//4,显示窗口
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);

//绘图1,拿到画图设备环境(拿到画布)DC
HDC hdc = GetDC(hwnd);// hdc的大小 跟窗口保持一致
HDC mdc = CreateCompatibleDC(hdc);// mdc大小不确定
HDC bufdc = CreateCompatibleDC(hdc);//bufdc大小不确定

HBITMAP whiteBmp = CreateCompatibleBitmap(hdc, 480, 852);
SelectObject(mdc, whiteBmp);

//绘图2,拿到图片
HBITMAP hBG = (HBITMAP)LoadImage(NULL, L"image/background.bmp", IMAGE_BITMAP, 480, 852, LR_LOADFROMFILE);
HBITMAP hTitle = (HBITMAP)LoadImage(NULL, L"image/title.bmp", IMAGE_BITMAP, 429, 84, LR_LOADFROMFILE);

SelectObject(bufdc, hBG);//先把图片放在中间层//bufdc的大小跟图片保持一直
//然后把中间层的东西直接拿到hdc上

BitBlt(mdc, 0, 0, 480, 852, bufdc, 0, 0, SRCCOPY);

SelectObject(bufdc, hTitle);
//BitBlt(mdc, 20, 50, 429, 84, bufdc, 0, 0, SRCCOPY);
TransparentBlt(mdc, 20, 50, 429, 84, bufdc, 0, 0, 429, 84, RGB(0, 0, 0));

BitBlt(hdc, 0, 0, 480, 852, mdc, 0, 0, SRCCOPY);

DeleteDC(bufdc);
DeleteDC(mdc);
ReleaseDC(hwnd, hdc);

//5,处理消息
MSG msg = { 0 };
while (msg.message != WM_QUIT)//当我们去到了一个退出的消息的时候,退出while循环
{
if (PeekMessage(&msg, 0, NULL, NULL, PM_REMOVE)) {// true取得消息 false 没有取得消息
TranslateMessage(&msg);
DispatchMessage(&msg);//交给 wndproc进行处理
}

}

//注销窗口
UnregisterClass(L"myclassname", hInstance);
return 0;
}

//用来处理窗口的事件(比如 键盘按键 鼠标事件 窗口关闭)
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lParam) {
switch (message)
{
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
MessageBox(NULL, L"检测到鼠标事件", L"这个是标题", 0);
break;
case WM_KEYDOWN://键盘按键按下
MessageBox(NULL, L"某个按键被按下了", L"这个是标题", 0);
break;
case WM_DESTROY://当我们点击窗口上的关闭按钮的时候,会收到这个destory的消息
//我们可以做一些窗口关闭之前的处理工作
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wparam, lParam);
}
return 0;
}

示例程序

微软示例程序win32窗口数字时钟程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <windows.h> 
#define ID_TIMER 1
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("DigClock");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
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 = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("Program requires Windows NT!"),
szAppName,
MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Digital Clock"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void DisplayDigit(HDC hdc, int iNumber)
{
static BOOL fSevenSegment[10][7] = {
1, 1, 1, 0, 1, 1, 1, // 0
0, 0, 1, 0, 0, 1, 0, // 1
1, 0, 1, 1, 1, 0, 1, // 2
1, 0, 1, 1, 0, 1, 1, // 3
0, 1, 1, 1, 0, 1, 0, // 4
1, 1, 0, 1, 0, 1, 1, // 5
1, 1, 0, 1, 1, 1, 1, // 6
1, 0, 1, 0, 0, 1, 0, // 7
1, 1, 1, 1, 1, 1, 1, // 8
1, 1, 1, 1, 0, 1, 1 }; // 9
static POINT ptSegment[7][6] = {
7, 6, 11, 2, 31, 2, 35, 6, 31, 10, 11, 10,
6, 7, 10, 11, 10, 31, 6, 35, 2, 31, 2, 11,
36, 7, 40, 11, 40, 31, 36, 35, 32, 31, 32, 11,
7 , 36, 11, 32, 31, 32, 35, 36, 31, 40, 11, 40,
6 , 37, 10, 41, 10, 61, 6, 65, 2, 61, 2, 41,
36, 37, 40, 41, 40, 61, 36, 65, 32, 61, 32, 41,
7 , 66, 11, 62, 31, 62, 35, 66, 31, 70, 11, 70 };
int iSeg;
for (iSeg = 0; iSeg < 7; iSeg++)
if (fSevenSegment[iNumber][iSeg])
Polygon(hdc, ptSegment[iSeg], 6);
}
void DisplayTwoDigits(HDC hdc, int iNumber, BOOL fSuppress)
{
if (!fSuppress || (iNumber / 10 != 0))
DisplayDigit(hdc, iNumber / 10);
OffsetWindowOrgEx(hdc, -42, 0, NULL);
DisplayDigit(hdc, iNumber % 10);
OffsetWindowOrgEx(hdc, -42, 0, NULL);
}
void DisplayColon(HDC hdc)
{
POINT ptColon[2][4] = { 2, 21, 6, 17, 10, 21, 6,
25, 2, 51, 6, 47, 10, 51, 6, 55 };
Polygon(hdc, ptColon[0], 4);
Polygon(hdc, ptColon[1], 4);
OffsetWindowOrgEx(hdc, -12, 0, NULL);
}
void DisplayTime(HDC hdc, BOOL f24Hour, BOOL fSuppress)
{
SYSTEMTIME st;
GetLocalTime(&st);
if (f24Hour)
DisplayTwoDigits(hdc, st.wHour, fSuppress);
else
DisplayTwoDigits(hdc, (st.wHour %= 12) ? st.wHour : 12, fSuppress);
DisplayColon(hdc);
DisplayTwoDigits(hdc, st.wMinute, FALSE);
DisplayColon(hdc);
DisplayTwoDigits(hdc, st.wSecond, FALSE);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
static BOOL f24Hour, fSuppress;
static HBRUSH hBrushRed;
static int cxClient, cyClient;
HDC hdc;
PAINTSTRUCT ps;
TCHAR szBuffer[2];
switch (message)
{
case WM_CREATE:
hBrushRed = CreateSolidBrush(RGB(255, 0, 0));
SetTimer(hwnd, ID_TIMER, 1000, NULL);// fall through
case WM_SETTINGCHANGE:
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2);
f24Hour = (szBuffer[0] == '1');
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITLZERO, szBuffer, 2);
fSuppress = (szBuffer[0] == '0');
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_TIMER:
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SetMapMode(hdc, MM_ISOTROPIC);
SetWindowExtEx(hdc, 276, 72, NULL);
SetViewportExtEx(hdc, cxClient, cyClient, NULL);
SetWindowOrgEx(hdc, 138, 36, NULL);
SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
SelectObject(hdc, GetStockObject(NULL_PEN));
SelectObject(hdc, hBrushRed);
DisplayTime(hdc, f24Hour, fSuppress);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
KillTimer(hwnd, ID_TIMER);
DeleteObject(hBrushRed);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

WinMain入口的窗口程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <windows.h>
#include <tchar.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASS wc = { 0 };
wc.lpszClassName = _T("MyBrowser");
wc.hInstance = hInstance;
wc.lpfnWndProc = DefWindowProc;
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
if (!RegisterClass(&wc))
return 1;
hWnd = CreateWindow(wc.lpszClassName, _T("My Browser"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 800, 600, NULL, NULL, hInstance, NULL);
if (!hWnd)
return 2;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}