离线
谢谢分享!
离线
#include <stdio.h>
#include <windows.h>
const wchar_t g_szClassName[] = L"myWindowClass";
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
MoveToEx(hdc,0,0,0);
LineTo(hdc,100,100);
Ellipse(hdc, 100, 100, 200, 200);
EndPaint(hWnd,&ps);
return;
}
void OnPaint2(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
HPEN hPen = CreatePen(PS_DASHDOTDOT, 2, NULL);
SelectObject(hdc, hPen);
Ellipse(hdc, 100, 200, 400, 400);
Ellipse(hdc, 300, 300, 500, 510);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_ERASEBKGND:
printf("erase back\n");
fflush(stdout);
return DefWindowProc(hwnd, msg, wParam, lParam);
case WM_MOVE:
printf("move\n");
fflush(stdout);
case WM_PAINT:
OnPaint(hwnd);
//MessageBoxW(hwnd, L"painting ...", L"p", MB_OK);
printf("painting...\n");
fflush(stdout);
//return DefWindowProc(hwnd, msg, wParam, lParam);
break;
case WM_LBUTTONDOWN:
//wchar_t szFileName[MAX_PATH];
//HINSTANCE hInstance = GetModuleHandle(NULL);
//GetModuleFileNameW(hInstance, szFileName, MAX_PATH);
//MessageBoxW(hwnd, szFileName, L"This program is:", MB_OK | MB_ICONINFORMATION);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEXW wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
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);
if(!RegisterClassExW(&wc))
{
MessageBoxW(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowExW(
WS_EX_CLIENTEDGE,
g_szClassName,
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBoxW(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (int)Msg.wParam;
}
mingw 编译: gcc -o test1 test1.c -luser32 -lgdi32
msvc 编译: cl test1.c gdi32.lib user32.lib
离线
搞不动windows的驱动
离线
手动撸的一个定时器更新 gdi 的demo:
#include <windows.h>
#define RECT_WIDTH 200
#define RECT_HEIGHT 200
// x and y are the x- and y-locations of the mouse cursor upon release
void drawRectangle(HWND hwnd, const int x, const int y)
{
// obtain a handle to the device context
HDC hdc = GetDC(hwnd);
// RECT_WIDTH and RECT_HEIGHT are elsewhere defined
// draw rectangle
Rectangle(hdc, x - RECT_WIDTH / 2, y - RECT_HEIGHT / 2, x + RECT_WIDTH / 2, y + RECT_HEIGHT / 2);
// release the DC
ReleaseDC(hwnd, hdc);
}
LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int x, y;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
{
SetTimer(hwnd, 0, 200, NULL);
break;
}
case WM_TIMER:
{
RECT rect;
do
{
x = rand();
}
while(x < 0 || x > 500);
do
{
y = rand();
}
while(y < 0 || y > 500);
GetClientRect(hwnd, &rect);
InvalidateRect(hwnd, &rect, 1);
break;
}
case WM_PAINT:
{
BeginPaint(hwnd, &ps);
// draw the rectangle
drawRectangle(hwnd, x, y);
EndPaint(hwnd, &ps);
return 0;
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
const wchar_t g_szClassName[] = L"myWindowClass";
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEXW wc;
HWND hwnd;
MSG Msg;
srand(0);
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
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);
if(!RegisterClassExW(&wc))
{
MessageBoxW(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowExW(
WS_EX_CLIENTEDGE,
g_szClassName,
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBoxW(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (int)Msg.wParam;
}
参考: https://stackoverflow.com/questions/28925178/drawing-rectangle-in-c-using-functions
离线
#include "Piece.h"
#include "Game.h"
#include <windows.h>
#include <iostream>
using namespace std;
const int PX_PER_BLOCK = 25; // Cell size in pixels
const int SCREEN_WIDTH = 10; // Level width in cells
const int SCREEN_HEIGHT = 20; // Level height in cells
const int GAME_SPEED = 33; // Update the game every GAME_SPEED millisecs (= 1/fps)
const int TIMER_ID = 1;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("tetris");
HWND hwnd;
MSG msg;
WNDCLASSEX wc;
// We need to repaint a lot, using CS_OWNDC is more efficient
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
wc.hIconSm = NULL;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, TEXT("Program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName,
TEXT("Eliang's Tetris"),
WS_MINIMIZEBOX | WS_SYSMENU, // No window resizing
CW_USEDEFAULT,
CW_USEDEFAULT,
SCREEN_WIDTH * PX_PER_BLOCK + 156,
SCREEN_HEIGHT * PX_PER_BLOCK + 25,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static Game *game;
static DrawEngine *de;
switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);
de = new DrawEngine(hdc, hwnd, PX_PER_BLOCK);
game = new Game(*de);
SetTimer(hwnd, TIMER_ID, GAME_SPEED, NULL);
ReleaseDC(hwnd, hdc);
return 0;
case WM_KEYDOWN:
game->keyPress(wParam);
return 0;
case WM_TIMER:
game->timerUpdate();
return 0;
case WM_KILLFOCUS:
KillTimer(hwnd, TIMER_ID);
game->pause(true);
return 0;
case WM_SETFOCUS:
SetTimer(hwnd, TIMER_ID, GAME_SPEED, NULL);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
game->repaint();
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
delete de;
delete game;
KillTimer(hwnd, TIMER_ID);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
https://github.com/eliangcs/tetris-win32
https://github.com/eliangcs/tetris-win32/blob/master/src/main.cpp
仅用 win32 api 做的俄罗斯方块。
离线
找到一个更精简的 俄罗斯方块: https://github.com/VincentJYZhang/tetris-game/tree/master/Source%20Code
TetrisGame_zjy.cpp
// TetrisGame_zjy.cpp
// by 张钧洋
// 2018.4.10
#include <windows.h>
#include <stdio.h>
#include <time.h>
#include "Shapes.h"
#define ID_TIMER 1
#define TIME_INTERVAL 1000 // 下落时间间隔1秒
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
VOID CALLBACK TimerProc(HWND, UINT, UINT, DWORD);
/*---------------宏-------------------*/
#define BOARD_WIDTH 180
#define BOARD_HEIGHT 400
#define LONG_SLEEP 300
#define COLS 15 // 列数
#define ROWS 30 // 行数
#define EXTENDED_COLS 23 // 包括不显示区域的列数
#define EXTENDED_ROWS 34 // 包括不显示区域的行数
// 游戏界面实际的方格位置
#define BOARD_LEFT 4
#define BOARD_RIGHT 18
#define BOARD_TOP 0
#define BOARD_BOTTOM 29
/*-----------------------------------*/
/*-------------参数声明---------------*/
// static int shapes[7][4][4];
static int shape[4][4];
static int score = 0;
static int shape_row = 0; // 当前形状所在行
static int shape_col = EXTENDED_COLS / 2 - 2; // 当前形状所在列
static int **gBoard;
static int lattices_top = 40; // 上面留白
static int lattices_left = 20; // 左侧留白
static int width = BOARD_WIDTH / COLS; //每个格子的宽度
static int height = (BOARD_HEIGHT - lattices_top) / ROWS; //每个格子的高度
static HBRUSH grey_brush = CreateSolidBrush(RGB(210, 210, 210));
static HBRUSH white_brush = CreateSolidBrush(RGB(255, 255, 255));
static HBRUSH red_brush = CreateSolidBrush(RGB(255, 0, 0));
static HBRUSH blue_brush = CreateSolidBrush(RGB(0, 0, 255));
static HPEN hPen = CreatePen(PS_SOLID, 1, RGB(147, 155, 166));
static bool gIsPause = false; // 判断是否暂停
/*-----------------------------------*/
/*-------------函数声明---------------*/
void InitGame(HWND);
void InitData();
void TypeInstruction(HWND);
void RandShape(); // 随机选择一个图形
void AddScore(); // 清空一行后加100分
void UpdateShapeRect(HWND hwnd); // 更新下落形状矩形区域
void UpdateAllBoard(HWND hwnd); // 更新游戏范围
void FallToGround();
void MoveDown(HWND hwnd); // 下降一格
void RePaintBoard(HDC hdc); // 重绘游戏界面
void PaintCell(HDC hdc, int x, int y, int color); // 绘制指定一个格子
void ClearFullLine(); // 清空满行
void RotateShape(HWND hwnd); // 图形变形
void MoveHori(HWND hwnd, int direction); // 水平移动
void RotateMatrix(); // 逆时针翻转图形
void ReRotateMatrix(); // 顺时针翻转图形
bool IsLegel(); // 检测图形是否超出范围
void RespondKey(HWND hwnd, WPARAM wParam); // 响应按键
void PauseGame(HWND hwnd); // 暂停游戏
void WakeGame(HWND hwnd); // 继续游戏
bool JudgeLose(); // 判断是否输
void LoseGame(HWND hwnd); // 游戏输了之后处理
void ExitGame(HWND hwnd); // 游戏结束
/*-----------------------------------*/
// 程序入口 WinMain
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("TetrisGame_Zjy");
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("Tetris Game"),
WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
BOARD_WIDTH + 220, BOARD_HEIGHT + 70,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
// 打印说明
TypeInstruction(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
// 窗口过程
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HDC hdc;
static HDC hdcBuffer;
static HBITMAP hBitMap;
static PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
SetTimer(hwnd, ID_TIMER, TIME_INTERVAL, TimerProc);
InitGame(hwnd);
TypeInstruction(hwnd);
return 0;
// 最小化恢复后需要重绘说明
case WM_SIZE:
TypeInstruction(hwnd);
return 0;
case WM_KEYDOWN:
RespondKey(hwnd, wParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
RePaintBoard(hdc);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
KillTimer(hwnd, ID_TIMER);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
// 计时器响应事件
VOID CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{
// 计时器每秒向下移动
MoveDown(hwnd);
}
// 初始化游戏
void InitGame(HWND hwnd) {
gBoard = new int*[EXTENDED_ROWS];
for (int i = 0; i < EXTENDED_ROWS; i++) {
gBoard[i] = new int[EXTENDED_COLS];
}
srand(time(0));
InitData();
UpdateAllBoard(hwnd);
}
// 初始化游戏数据
void InitData() {
// 将游戏面板清零
for (int i = 0; i < EXTENDED_ROWS; i++) {
for (int j = 0; j < EXTENDED_COLS; j++) {
gBoard[i][j] = 0;
}
}
// 将外围填充1,为了判断是否超出范围
for (int i = 0; i < EXTENDED_ROWS; i++) {
for (int j = 0; j < BOARD_LEFT; j++) {
gBoard[i][j] = 1;
}
}
for (int i = 0; i < EXTENDED_ROWS; i++) {
for (int j = BOARD_RIGHT + 1; j < EXTENDED_COLS; j++) {
gBoard[i][j] = 1;
}
}
for (int i = BOARD_BOTTOM + 1; i < EXTENDED_ROWS; i++) {
for (int j = 0; j < EXTENDED_COLS; j++) {
gBoard[i][j] = 1;
}
}
gIsPause = false;
// 初始化分数
score = 0;
// 随机生成图形
RandShape();
return;
}
// 打印说明
void TypeInstruction(HWND hwnd) {
TEXTMETRIC tm;
int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth;
HDC hdc = GetDC(hwnd);
// 保存行高字宽信息
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;
cyChar = tm.tmHeight + tm.tmExternalLeading;
int startX = 180;
int startY = 40;
TCHAR Instruction[100];
// 打印说明
wsprintf(Instruction, TEXT("INSTRUCTION "));
TextOut(hdc, startX + 40, startY, Instruction, lstrlen(Instruction));
wsprintf(Instruction, TEXT("↑ Change Shape"));
TextOut(hdc, startX + 40, startY + cyChar * 3, Instruction, lstrlen(Instruction));
wsprintf(Instruction, TEXT("← Move Left"));
TextOut(hdc, startX + 40, startY + cyChar * 5, Instruction, lstrlen(Instruction));
wsprintf(Instruction, TEXT("→ Move Right"));
TextOut(hdc, startX + 40, startY + cyChar * 7, Instruction, lstrlen(Instruction));
wsprintf(Instruction, TEXT("↓ Move Down"));
TextOut(hdc, startX + 40, startY + cyChar * 9, Instruction, lstrlen(Instruction));
wsprintf(Instruction, TEXT("Space Pause the game"));
TextOut(hdc, startX + 40, startY + cyChar * 11, Instruction, lstrlen(Instruction));
wsprintf(Instruction, TEXT("Esc Exit the game"));
TextOut(hdc, startX + 40, startY + cyChar * 13, Instruction, lstrlen(Instruction));
wsprintf(Instruction, TEXT("© 2018.4 张钧洋"));
TextOut(hdc, startX + 40, startY + cyChar * 18, Instruction, lstrlen(Instruction));
ReleaseDC(hwnd, hdc);
}
// 随机选中一个图形
void RandShape() {
int shape_num = rand() % 7;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
shape[i][j] = shapes[shape_num][i][j];
}
// 更新整个游戏界面
void UpdateAllBoard(HWND hwnd) {
static RECT rect;
rect.left = lattices_left;
rect.right = lattices_left + COLS * width + width;
rect.top = lattices_top - 30;
rect.bottom = lattices_top + ROWS * height;
// 这个矩形包括了游戏界面方格,但不包括右侧的说明
InvalidateRect(hwnd, &rect, false);
}
// 更新下落形状所在矩形区域内
void UpdateShapeRect(HWND hwnd) {
static RECT rect;
rect.left = lattices_left;
rect.right = lattices_left + COLS * width + width;
rect.top = lattices_top + (shape_row - 1) * height;
rect.bottom = lattices_top + (shape_row + 4) * height;
InvalidateRect(hwnd, &rect, false);
}
// 重绘游戏界面
void RePaintBoard(HDC hdc) {
SetBkColor(hdc, RGB(255, 255, 255));
SelectObject(hdc, hPen); //选用画笔
TCHAR score_str[50];
// 绘制当前分数
wsprintf(score_str, TEXT("Score: %5d "), score);
TextOut(hdc, 20, 15, score_str, lstrlen(score_str));
// 绘制游戏界面背景
for (int i = BOARD_TOP; i <= BOARD_BOTTOM; i++) {
for (int j = BOARD_LEFT; j <= BOARD_RIGHT; j++) {
PaintCell(hdc, i, j, gBoard[i][j]);
}
}
// 绘制正在下降的图形
for (int i = 0; i < 4; i++) {
for (int j = 0; j<4; j++) {
if (shape[i][j] == 1)
PaintCell(hdc, shape_row + i, shape_col + j, shape[i][j]);
}
}
}
// 打印指定位置指定颜色的方格
void PaintCell(HDC hdc, int x, int y, int color) {
// 超出范围直接结束
if (x < BOARD_TOP || x > BOARD_BOTTOM ||
y < BOARD_LEFT || y > BOARD_RIGHT) {
return;
}
x -= BOARD_TOP;
y -= BOARD_LEFT;
// 将坐标换算为实际的像素点
int _left = lattices_left + y * width;
int _right = lattices_left + y * width + width;
int _top = lattices_top + x * height;
int _bottom = lattices_top + x * height + height;
// 绘制边框
MoveToEx(hdc, _left, _top, NULL);
LineTo(hdc, _right, _top);
MoveToEx(hdc, _left, _top, NULL);
LineTo(hdc, _left, _bottom);
MoveToEx(hdc, _left, _bottom, NULL);
LineTo(hdc, _right, _bottom);
MoveToEx(hdc, _right, _top, NULL);
LineTo(hdc, _right, _bottom);
if (color == 0) {
SelectObject(hdc, white_brush);
}
else if (color == 1) {
SelectObject(hdc, blue_brush);
}
else if (color == 2) {
SelectObject(hdc, red_brush);
}
// 填充
Rectangle(hdc, _left, _top, _right, _bottom);
}
// 响应按键
void RespondKey(HWND hwnd, WPARAM wParam) {
if (wParam == VK_ESCAPE) {//ESC退出
ExitGame(hwnd);
return;
}
if (wParam == VK_SPACE) {//空格暂停
gIsPause = !gIsPause;
if (gIsPause == true) {
PauseGame(hwnd);
return;
}
else {
WakeGame(hwnd);
return;
}
}
// 如果处于暂停状态下就不响应这些移动操作
if (!gIsPause) {
if (wParam == VK_UP) {
RotateShape(hwnd);
return;
}
if (wParam == VK_DOWN) {
MoveDown(hwnd);
return;
}
if (wParam == VK_LEFT) {
MoveHori(hwnd, 0);
return;
}
if (wParam == VK_RIGHT) {
MoveHori(hwnd, 1);
return;
}
}
}
// 停止计数器
void PauseGame(HWND hwnd) {
KillTimer(hwnd, ID_TIMER);
}
// 重启计数器
void WakeGame(HWND hwnd) {
SetTimer(hwnd, ID_TIMER, TIME_INTERVAL, TimerProc);
}
// 退出游戏
void ExitGame(HWND hwnd) {
// 先暂停游戏
SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
// 是否退出
int flag = MessageBox(NULL, TEXT("Do you want exit?"), TEXT("EXIT"), MB_YESNO);
if (flag == IDYES) {
SendMessage(hwnd, WM_DESTROY, NULL, 0);
}
else if (flag == IDNO) {
return;
}
}
// 图形变形
void RotateShape(HWND hwnd) {
RotateMatrix();
if (!IsLegel()) {
ReRotateMatrix();
}
UpdateShapeRect(hwnd);
return;
}
// 判断形状是否在游戏界面中
bool IsLegel() {
for (int i = 0; i<4; i++)
for (int j = 0; j<4; j++)
if (shape[i][j] == 1 &&
(gBoard[shape_row + i][shape_col + j] == 1 ||
gBoard[shape_row + i][shape_col + j] == 2))
return false;
return true;
}
// 逆时针旋转当前下落的形状
void RotateMatrix() {
int(*a)[4] = shape;
int s = 0;
for (int n = 4; n >= 1; n -= 2) {
for (int i = 0; i < n - 1; i++) {
int t = a[s + i][s];
a[s + i][s] = a[s][s + n - i - 1];
a[s][s + n - i - 1] = a[s + n - i - 1][s + n - 1];
a[s + n - i - 1][s + n - 1] = a[s + n - 1][s + i];
a[s + n - 1][s + i] = t;
}
s++;
}
}
// 如果超出范围,将形状恢复(顺时针旋转)
void ReRotateMatrix() {
int(*a)[4] = shape;
int s = 0;
for (int n = 4; n >= 1; n -= 2) {
for (int i = 0; i<n - 1; i++) {
int t = a[s + i][s];
a[s + i][s] = a[s + n - 1][s + i];
a[s + n - 1][s + i] = a[s + n - i - 1][s + n - 1];
a[s + n - i - 1][s + n - 1] = a[s][s + n - i - 1];
a[s][s + n - i - 1] = t;
}
s++;
}
}
// 下落形状下降一格
void MoveDown(HWND hwnd) {
shape_row++;
if (!IsLegel()) {
shape_row--;
if (JudgeLose()) {
LoseGame(hwnd);
return;
}
FallToGround();
ClearFullLine();
UpdateAllBoard(hwnd);
// 重置下落形状位置
shape_row = 0;
shape_col = EXTENDED_COLS / 2 - 2;
RandShape();
}
UpdateShapeRect(hwnd);
}
// 判断是否输了
bool JudgeLose() {
if (shape_row == 0)
return true;
return false;
}
// 游戏结束
void LoseGame(HWND hwnd) {
SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
TCHAR words[100];
wsprintf(words, TEXT("You lose the Game. Your score is %d. \nDo you want try again?"), score);
int flag = MessageBox(NULL, words, TEXT("EXIT"), MB_YESNO);
if (flag == IDYES) {
SendMessage(hwnd, WM_CREATE, NULL, 0);
return;
}
else if (flag == IDNO) {
SendMessage(hwnd, WM_DESTROY, NULL, 0);
return;
}
}
// 图形落地,更新背景数组
void FallToGround() {
for (int i = 0; i<4; i++) {
for (int j = 0; j<4; j++) {
gBoard[shape_row + i][shape_col + j] = shape[i][j] == 1 ? 2 : gBoard[shape_row + i][shape_col + j];
}
}
}
// 清除整行的方格
void ClearFullLine() {
for (int i = shape_row; i <= shape_row + 3; i++) {
if (i > BOARD_BOTTOM)
continue;
bool there_is_blank = false;
// 判断一行是否有空格
for (int j = BOARD_LEFT; j <= BOARD_RIGHT; j++) {
if (gBoard[i][j] == 0) {
there_is_blank = true;
break;
}
}
if (!there_is_blank) {
AddScore();
for (int r = i; r >= 1; r--) {
for (int c = BOARD_LEFT; c <= BOARD_RIGHT; c++) {
gBoard[r][c] = gBoard[r - 1][c];
}
}
}
}
}
// 清除一行加100分
void AddScore() {
score += 100;
}
// 下落形状水平方向移动
void MoveHori(HWND hwnd, int direction) {
int temp = shape_col;
// direction 为0则左移否则右移
if (direction == 0)
shape_col--;
else
shape_col++;
// 如果移动后位置超出边界
if (!IsLegel()) {
shape_col = temp;
}
UpdateShapeRect(hwnd);
return;
}
Shapes.h
#ifndef SHAPES_H
#define SHAPES_H
// 存储七种形状
static int shapes[7][4][4] = {
{
{ 0, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 1, 1, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 },
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 1, 1, 0, 0 },
{ 0, 0, 0, 0 }
}
};
#endif // !SHAPES_H
离线
上面代码用 mingw 编译还有点坑, 要 notepad++ 转码一下
g++ -o test TetrisGame_zjy.c -lgdi32 -luser32 -DUNICODE
咦, 为什么背后还要启动一个黑窗口呢?
离线
启动了控制台调试吧?
离线
启动了控制台调试吧?
g++ -o test TetrisGame_zjy.c -lgdi32 -luser32 -DUNICODE
这个编译指令要加点什么吗?
离线
优秀 围观
离线
#include <stdio.h>
#include <windows.h>
#define ID_TIMER 1
const wchar_t g_szClassName[] = L"myWindowClass";
void OnTimer(HWND hWnd)
{
printf("on timer...\n");
fflush(stdout);
}
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP membmp =CreateCompatibleBitmap(hdc, ps.rcPaint.right, ps.rcPaint.bottom);
HGDIOBJ oldBitmap=SelectObject(memdc, membmp);
//SetMapMode(memdc, GetMapMode(hdc));
const RECT rect = {10, 10, 300, 100};
//SetBkColor(memdc, RGB(0xFF, 0xFF, 0xFF));
FillRect(memdc, &ps.rcPaint, CreateSolidBrush(RGB(255,255,255)));
FillRect(memdc, &rect, CreateSolidBrush(RGB(255, 0, 0)));
LineTo(memdc, 100, 100);
Ellipse(memdc, 150, 150, 250, 200);
BitBlt(hdc,0,0,ps.rcPaint.right, ps.rcPaint.bottom,memdc,0,0,SRCCOPY);
DeleteObject(SelectObject(memdc, oldBitmap));
DeleteDC(memdc);
DeleteDC(hdc);
EndPaint(hWnd,&ps);
return;
}
void OnPaint1(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
const RECT rect = {10, 10, 300, 100};
FillRect(hdc, &rect, CreateSolidBrush(RGB(255, 0, 0)));
MoveToEx(hdc,0,0,0);
LineTo(hdc, 100, 100);
Ellipse(hdc, 100, 100, 200, 200);
EndPaint(hWnd,&ps);
return;
}
void OnPaint2(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
HPEN hPen = CreatePen(PS_DASHDOTDOT, 2, NULL);
SelectObject(hdc, hPen);
Ellipse(hdc, 100, 200, 400, 400);
Ellipse(hdc, 300, 300, 500, 510);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
//SetTimer(hwnd, ID_TIMER, 2000, NULL);
break;
case WM_TIMER:
OnTimer(hwnd);
break;
case WM_ERASEBKGND:
printf("erase back\n");
fflush(stdout);
return DefWindowProc(hwnd, msg, wParam, lParam);
case WM_MOVE:
printf("move\n");
fflush(stdout);
case WM_PAINT:
OnPaint(hwnd);
//MessageBoxW(hwnd, L"painting ...", L"p", MB_OK);
printf("painting...\n");
fflush(stdout);
//return DefWindowProc(hwnd, msg, wParam, lParam);
break;
case WM_LBUTTONDOWN:
//wchar_t szFileName[MAX_PATH];
//HINSTANCE hInstance = GetModuleHandle(NULL);
//GetModuleFileNameW(hInstance, szFileName, MAX_PATH);
//MessageBoxW(hwnd, szFileName, L"This program is:", MB_OK | MB_ICONINFORMATION);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEXW wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
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);
if(!RegisterClassExW(&wc))
{
MessageBoxW(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowExW(
WS_EX_CLIENTEDGE,
g_szClassName,
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBoxW(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (int)Msg.wParam;
}
用双缓冲画图 OK
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP membmp =CreateCompatibleBitmap(hdc, ps.rcPaint.right, ps.rcPaint.bottom);
HGDIOBJ oldBitmap=SelectObject(memdc, membmp);
//SetMapMode(memdc, GetMapMode(hdc));
const RECT rect = {10, 10, 300, 100};
//SetBkColor(memdc, RGB(0xFF, 0xFF, 0xFF));
FillRect(memdc, &ps.rcPaint, CreateSolidBrush(RGB(255,255,255)));
FillRect(memdc, &rect, CreateSolidBrush(RGB(255, 0, 0)));
LineTo(memdc, 100, 100);
Ellipse(memdc, 150, 150, 250, 200);
BitBlt(hdc,0,0,ps.rcPaint.right, ps.rcPaint.bottom,memdc,0,0,SRCCOPY);
DeleteObject(SelectObject(memdc, oldBitmap));
DeleteDC(memdc);
DeleteDC(hdc);
EndPaint(hWnd,&ps);
return;
}
离线
g++ -o test TetrisGame_zjy.c -lgdi32 -luser32 -DUNICODE
这个编译指令要加点什么吗?
终于搞定,
g++ -o test TetrisGame_zjy.c -lgdi32 -luser32 -DUNICODE -mwindows
这样就没有黑窗口了。
https://stackoverflow.com/questions/13100785/mingw-build-gui-application-with-console
离线
定时器调用 InvalidateRect() 使客户区域无效,gui系统会自动发出 WM_PAINT 消息,
窗口消息处理函数收到WM_PAINT消息自动显示随机颜色。
void OnTimer(HWND hWnd)
{
printf("on timer...\n");
fflush(stdout);
RECT rect;
GetClientRect(hWnd, &rect);
InvalidateRect(hWnd, &rect, FALSE);
}
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP membmp =CreateCompatibleBitmap(hdc, ps.rcPaint.right, ps.rcPaint.bottom);
HGDIOBJ oldBitmap=SelectObject(memdc, membmp);
//SetMapMode(memdc, GetMapMode(hdc));
const RECT rect = {10, 10, 300, 100};
//SetBkColor(memdc, RGB(0xFF, 0xFF, 0xFF));
FillRect(memdc, &ps.rcPaint, CreateSolidBrush(RGB(255,255,255)));
FillRect(memdc, &rect, CreateSolidBrush(RGB(rand()%0xFF, rand()%0xFF, rand()%0xFF)));
LineTo(memdc, 100, 100);
Ellipse(memdc, 150, 150, 250, 200);
BitBlt(hdc,0,0,ps.rcPaint.right, ps.rcPaint.bottom,memdc,0,0,SRCCOPY);
DeleteObject(SelectObject(memdc, oldBitmap));
DeleteDC(memdc);
DeleteDC(hdc);
EndPaint(hWnd,&ps);
return;
}
离线
感觉现在已经很少有人裸写win32 api gui了,都是用一些界面库来实现了
离线
感觉现在已经很少有人裸写win32 api gui了,都是用一些界面库来实现了
为了修改公司的一个祖传MFC软件, 不得不学习一下win32 基础编程.
离线
https://docs.microsoft.com/en-us/windows/win32/controls/create-toolbars
https://docs.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_create
HIMAGELIST g_hImageList = NULL;
HWND CreateSimpleToolbar(HWND hWndParent)
{
// Declare and initialize local constants.
const int ImageListID = 0;
const int numButtons = 3;
const int bitmapSize = 16;
const DWORD buttonStyles = BTNS_AUTOSIZE;
// Create the toolbar.
HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0,
hWndParent, NULL, g_hInst, NULL);
if (hWndToolbar == NULL)
return NULL;
// Create the image list.
g_hImageList = ImageList_Create(bitmapSize, bitmapSize, // Dimensions of individual bitmaps.
ILC_COLOR16 | ILC_MASK, // Ensures transparent background.
numButtons, 0);
// Set the image list.
SendMessage(hWndToolbar, TB_SETIMAGELIST,
(WPARAM)ImageListID,
(LPARAM)g_hImageList);
// Load the button images.
SendMessage(hWndToolbar, TB_LOADIMAGES,
(WPARAM)IDB_STD_SMALL_COLOR,
(LPARAM)HINST_COMMCTRL);
// Initialize button info.
// IDM_NEW, IDM_OPEN, and IDM_SAVE are application-defined command constants.
TBBUTTON tbButtons[numButtons] =
{
{ MAKELONG(STD_FILENEW, ImageListID), IDM_NEW, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"New" },
{ MAKELONG(STD_FILEOPEN, ImageListID), IDM_OPEN, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Open"},
{ MAKELONG(STD_FILESAVE, ImageListID), IDM_SAVE, 0, buttonStyles, {0}, 0, (INT_PTR)L"Save"}
};
// Add buttons.
SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessage(hWndToolbar, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);
// Resize the toolbar, and then show it.
SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(hWndToolbar, TRUE);
return hWndToolbar;
}
借鉴微软这段代码, 自己写了一个:
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
const wchar_t g_szClassName[] = L"myWindowClass";
HIMAGELIST g_hImageList = NULL;
#define IDM_NEW 100
#define IDM_OPEN 101
#define IDM_SAVE 102
HINSTANCE gInstance;
HWND CreateSimpleToolbar(HWND hWndParent)
{
// Declare and initialize local constants.
const int ImageListID = 0;
const int numButtons = 3;
const int bitmapSize = 16;
const DWORD buttonStyles = BTNS_AUTOSIZE;
// Create the toolbar.
HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0,
hWndParent, NULL, gInstance, NULL);
if (hWndToolbar == NULL)
return NULL;
// Create the image list.
g_hImageList = ImageList_Create(bitmapSize, bitmapSize, // Dimensions of individual bitmaps.
ILC_COLOR16 | ILC_MASK, // Ensures transparent background.
numButtons, 0);
// Set the image list.
SendMessage(hWndToolbar, TB_SETIMAGELIST,
(WPARAM)ImageListID,
(LPARAM)g_hImageList);
// Load the button images.
SendMessage(hWndToolbar, TB_LOADIMAGES,
(WPARAM)IDB_STD_SMALL_COLOR,
(LPARAM)HINST_COMMCTRL);
// Initialize button info.
// IDM_NEW, IDM_OPEN, and IDM_SAVE are application-defined command constants.
TBBUTTON tbButtons[numButtons] =
{
{ MAKELONG(STD_FILENEW, ImageListID), IDM_NEW, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"New" },
{ MAKELONG(STD_FILEOPEN, ImageListID), IDM_OPEN, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Open"},
{ MAKELONG(STD_FILESAVE, ImageListID), IDM_SAVE, 0, buttonStyles, {0}, 0, (INT_PTR)L"Save"}
};
// Add buttons.
SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessage(hWndToolbar, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);
// Resize the toolbar, and then show it.
SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(hWndToolbar, TRUE);
return hWndToolbar;
}
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
MoveToEx(hdc, 0, 0, 0);
LineTo(hdc, 100, 100);
Ellipse(hdc, 100, 100, 200, 200);
EndPaint(hWnd, &ps);
return;
}
void OnPaint2(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
HPEN hPen = CreatePen(PS_DASHDOTDOT, 2, NULL);
SelectObject(hdc, hPen);
Ellipse(hdc, 100, 200, 400, 400);
Ellipse(hdc, 300, 300, 500, 510);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
CreateSimpleToolbar(hwnd);
case WM_ERASEBKGND:
printf("erase back\n");
fflush(stdout);
return DefWindowProc(hwnd, msg, wParam, lParam);
case WM_MOVE:
printf("move\n");
fflush(stdout);
case WM_PAINT:
OnPaint(hwnd);
//MessageBoxW(hwnd, L"painting ...", L"p", MB_OK);
printf("painting...\n");
fflush(stdout);
//return DefWindowProc(hwnd, msg, wParam, lParam);
break;
case WM_LBUTTONDOWN:
//wchar_t szFileName[MAX_PATH];
//HINSTANCE hInstance = GetModuleHandle(NULL);
//GetModuleFileNameW(hInstance, szFileName, MAX_PATH);
//MessageBoxW(hwnd, szFileName, L"This program is:", MB_OK | MB_ICONINFORMATION);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEXW wc;
HWND hwnd;
MSG Msg;
gInstance = hInstance;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
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);
if (!RegisterClassExW(&wc))
{
MessageBoxW(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowExW(
WS_EX_CLIENTEDGE,
g_szClassName,
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
MessageBoxW(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (int)Msg.wParam;
}
离线
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
const wchar_t g_szClassName[] = L"myWindowClass";
HIMAGELIST g_hImageList = NULL;
#define IDM_NEW 100
#define IDM_OPEN 101
#define IDM_SAVE 102
HINSTANCE gInstance;
HWND CreateSimpleToolbar(HWND hWndParent)
{
// Declare and initialize local constants.
const int ImageListID = 0;
const int numButtons = 3;
const int bitmapSize = 16;
const DWORD buttonStyles = BTNS_AUTOSIZE;
// Create the toolbar.
HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0,
hWndParent, NULL, gInstance, NULL);
if (hWndToolbar == NULL)
return NULL;
// Create the image list.
g_hImageList = ImageList_Create(bitmapSize, bitmapSize, // Dimensions of individual bitmaps.
ILC_COLOR16 | ILC_MASK, // Ensures transparent background.
numButtons, 0);
// Set the image list.
SendMessage(hWndToolbar, TB_SETIMAGELIST,
(WPARAM)ImageListID,
(LPARAM)g_hImageList);
// Load the button images.
SendMessage(hWndToolbar, TB_LOADIMAGES,
(WPARAM)IDB_STD_SMALL_COLOR,
(LPARAM)HINST_COMMCTRL);
// Initialize button info.
// IDM_NEW, IDM_OPEN, and IDM_SAVE are application-defined command constants.
TBBUTTON tbButtons[numButtons] =
{
{ MAKELONG(STD_FILENEW, ImageListID), IDM_NEW, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"New" },
{ MAKELONG(STD_FILEOPEN, ImageListID), IDM_OPEN, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Open"},
{ MAKELONG(STD_FILESAVE, ImageListID), IDM_SAVE, 0, buttonStyles, {0}, 0, (INT_PTR)L"Save"}
};
// Add buttons.
SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessage(hWndToolbar, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);
// Resize the toolbar, and then show it.
SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
ShowWindow(hWndToolbar, TRUE);
return hWndToolbar;
}
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
MoveToEx(hdc, 0, 0, 0);
LineTo(hdc, 100, 100);
Ellipse(hdc, 100, 100, 200, 200);
EndPaint(hWnd, &ps);
return;
}
void OnPaint2(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
HPEN hPen = CreatePen(PS_DASHDOTDOT, 2, NULL);
SelectObject(hdc, hPen);
Ellipse(hdc, 100, 200, 400, 400);
Ellipse(hdc, 300, 300, 500, 510);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
CreateSimpleToolbar(hwnd);
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
int wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_NEW:
MessageBox(hwnd, _TEXT("点击了new"), _TEXT("提示"), 0);
break;
case IDM_OPEN:
MessageBox(hwnd, _TEXT("点击了open"), _TEXT("提示"), 0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
break;
case WM_ERASEBKGND:
printf("erase back\n");
fflush(stdout);
return DefWindowProc(hwnd, msg, wParam, lParam);
case WM_MOVE:
printf("move\n");
fflush(stdout);
case WM_PAINT:
OnPaint(hwnd);
//MessageBoxW(hwnd, L"painting ...", L"p", MB_OK);
printf("painting...\n");
fflush(stdout);
//return DefWindowProc(hwnd, msg, wParam, lParam);
break;
case WM_LBUTTONDOWN:
//wchar_t szFileName[MAX_PATH];
//HINSTANCE hInstance = GetModuleHandle(NULL);
//GetModuleFileNameW(hInstance, szFileName, MAX_PATH);
//MessageBoxW(hwnd, szFileName, L"This program is:", MB_OK | MB_ICONINFORMATION);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEXW wc;
HWND hwnd;
MSG Msg;
gInstance = hInstance;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
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);
if (!RegisterClassExW(&wc))
{
MessageBoxW(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowExW(
WS_EX_CLIENTEDGE,
g_szClassName,
L"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
MessageBoxW(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (int)Msg.wParam;
}
添加了工具栏 toolbar wm_command 消息响应代码.
离线
多谢分享
离线