§ Основной код
* hInstance Переданная текущая программа
* hPrevInstance Программа, которая передала управление
* lpCmdLine Строка запроса (нулевой символ в конце)
* nShowCmd Показывает состояние окна
Подробное описание
в этой статье.
@echo off
g++ -m32 -g3 -static-libgcc -mwindows -lgdi32 main.cpp -o main.exe
strip main.exe
main.exe
§ Файл main.cpp
#include "demoapp.cpp"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
DemoApp app;
app.init(hInstance, 1280, 800, "Windows", 50, 4);
int test = 0;
while (app.wait()) {
if (app.is_timer()) {
test++;
for (int y = 0; y < 200; y++)
for (int x = 0; x < 320; x++)
app.pset(x, y, x*y + test);
}
app.repaint();
}
return 0;
}
§ Класс-обработчик demoapp.cpp
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "demoapp.h"
class DemoApp {
protected:
HWND hWnd;
INT64 frameMillisecond;
int last_events;
public:
void init(HINSTANCE hInstance, int width, int height, const char* name, int fps, int scale) {
DWORD dwExStyle = WS_EX_APPWINDOW;
DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
int x, y, w, h;
WNDCLASS wc;
RECT rc;
wc.style = CS_OWNDC;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("MainWndEx");
if (!RegisterClass(&wc)) {
MessageBox(NULL, TEXT("RegisterClass failed!"), TEXT("Error"), MB_ICONERROR | MB_OK | MB_SETFOREGROUND);
return;
}
rc.left = 0;
rc.top = 0;
rc.right = width;
rc.bottom = height;
window_width = width;
window_height = height;
win_ws = window_width / scale;
win_hs = window_height / scale;
if (!AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle)) {
MessageBox(NULL, TEXT("AdjustWindowRectEx failed!"), TEXT("Error"), MB_ICONERROR | MB_OK | MB_SETFOREGROUND);
return;
}
w = width;
h = height;
x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2;
y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
EventAccept = 0;
last_events = 0;
frameMillisecond = 1000 / fps;
pixels = (COLORREF*) malloc (width * height * sizeof(COLORREF));
hWnd = CreateWindowEx(dwExStyle, wc.lpszClassName, name, dwStyle, x, y, w, h, NULL, NULL, hInstance, NULL);
if (!hWnd) {
MessageBox(NULL, TEXT("CreateWindowEx failed."), TEXT("Error"), MB_ICONERROR | MB_OK | MB_SETFOREGROUND);
return;
}
bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo);
bitmapInfo.bmiHeader.biWidth = width / scale;
bitmapInfo.bmiHeader.biHeight = -height / scale;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
SetTimer(hWnd, 0, frameMillisecond, NULL);
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
}
void repaint() {
if (is_timer()) {
InvalidateRect(hWnd, NULL, FALSE);
}
}
int is_timer() {
return last_events & MYEVENT_WM_TIMER ? 1 : 0;
}
int is_keydown() { return last_events & MYEVENT_WM_KEYDOWN ? 1 : 0; }
int is_keyup() { return last_events & MYEVENT_WM_KEYUP ? 1 : 0; }
int kb_key() { return DataKeyboard; }
int peek_messages() {
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
return 0;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
Sleep(1);
return 1;
}
int wait() {
EventAccept = 0;
do {
if (peek_messages() == 0)
return 0;
} while (!EventAccept);
last_events = EventAccept;
return EventAccept;
}
void pset(int x, int y, int color) {
if (x >= 0 && y >= 0 && x < win_ws && y < win_hs) {
pixels[win_ws*y + x] = color;
}
}
void line(int x1, int y1, int x2, int y2, int color) {
int deltax = abs(x2 - x1);
int deltay = abs(y2 - y1);
int signx = x1 < x2 ? 1 : -1;
int signy = y1 < y2 ? 1 : -1;
int error = deltax - deltay;
int error2;
pset(x2, y2, color);
while (x1 != x2 || y1 != y2)
{
pset(x1, y1, color);
error2 = error * 2;
if (error2 > -deltay) {
error -= deltay;
x1 += signx;
}
if (error2 < deltax) {
error += deltax;
y1 += signy;
}
}
}
void cls(int color) {
for (int i = 0; i < win_ws * win_hs; i++)
pixels[i] = color;
}
};
LRESULT CALLBACK MainWndProc(HWND MyWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE:
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_ERASEBKGND:
return TRUE;
case WM_KEYDOWN:
EventAccept |= MYEVENT_WM_KEYDOWN;
DataKeyboard = wParam;
return 0;
case WM_KEYUP:
EventAccept |= MYEVENT_WM_KEYUP;
DataKeyboard = wParam;
return 0;
case WM_TIMER:
EventAccept |= MYEVENT_WM_TIMER;
return 0;
case WM_PAINT:
PAINTSTRUCT ps;
RECT r;
HDC hDC;
hDC = BeginPaint(MyWnd, &ps);
GetClientRect(MyWnd, &r);
StretchDIBits(
hDC,
0, 0, window_width, window_height,
0, 0, win_ws, win_hs,
pixels, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
EndPaint(MyWnd, &ps);
return 0;
}
return DefWindowProc(MyWnd, msg, wParam, lParam);
}
§ Заголовочный файл demoapp.h
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow);
int window_width, window_height;
int win_ws, win_hs;
int EventAccept;
WPARAM DataKeyboard;
static COLORREF* pixels;
static BITMAPINFO bitmapInfo;
enum Events {
MYEVENT_WM_TIMER = 1,
MYEVENT_WM_KEYDOWN = 2,
MYEVENT_WM_KEYUP = 4,
};