ガンダムネットワーク大戦で使えるエリア確認アプリケーションを作りました
苦労した点はウィンドウを六角形に変形させたことと半透明にすることでした
このアプリケーションは前にC#/VB.netで作ってましたがフレームワークを別途インストールしないといけないという欠点がありました
このプログラムではEXEファイル単体で動きます
■注目関数
○最前面に固定
CreateWindowEx WS_EX_TOPMOSTパラメーター
○六角形にウィンドウを加工
CreatePolygonRgn
SetWindowRgn
○ウィンドウを半透明にする
CreateWindowEx WS_EX_LAYEREDパラメーター
SetLayeredWindowAttributes
○左ドラッグでウィンドウを移動
PostMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam);
#include <windows.h>
#include "resource.h"
#include <objidl.h>
#include <gdiplus.h>
#include <cmath>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
VOID OnPaint(HWND hwnd, HDC hdc,int height, int width)
{
static POINT pt[7];
HRGN hrgn;
pt[0].x = width / 2 + height / 2 * -std::cos(45);
pt[0].y = 0;
pt[1].x = width / 2 + width / 2 * std::cos(45);
pt[1].y = 0;
pt[2].x = width;
pt[2].y = height / 2;
pt[3].x = width / 2 + width / 2 * std::cos(45);
pt[3].y = height;
pt[4].x = width / 2 + width / 2 * -std::cos(45);
pt[4].y = height;
pt[5].x = 0;
pt[5].y = height / 2;
pt[6].x = width / 2 + width / 2 * -std::cos(45);
pt[6].y = 0;
hrgn = CreatePolygonRgn(pt, 7, ALTERNATE);
SetWindowRgn(hwnd, hrgn, TRUE);
Graphics graphics(hdc);
Pen pen(Color(255, 125, 125, 125), 1);
graphics.DrawLine(&pen, (int)(width / 2), 0, (int)(width / 2), (int)(height));
graphics.DrawLine(&pen, 0, (int)(height / 2), (int)(width), (int)(height / 2));
graphics.DrawLine(&pen, (int)(width / 2), (int)(height / 2), (int)(width / 2 + width / 2 * -std::cos(45)), 0);
graphics.DrawLine(&pen, (int)(width / 2), (int)(height / 2), (int)(width / 2 + width / 2 * std::cos(45)), (int)(height));
graphics.DrawLine(&pen, (int)(width / 2), (int)(height / 2), (int)(width / 2 + width / 2 * std::cos(45)), 0);
graphics.DrawLine(&pen, (int)(width / 2), (int)(height / 2), (int)(width / 2 + width / 2 * -std::cos(45)), (int)(height));
graphics.DrawLine(&pen, (int)(width / 2 + width / 2 * -std::cos(45)), 0, 0, (int)(height / 2));
graphics.DrawLine(&pen, 0, (int)(height / 2), (int)(width / 2 + width / 2 * -std::cos(45)), (int)(height));
graphics.DrawLine(&pen, (int)(width / 2 + width / 2 * std::cos(45)), 0, (int)(width), (int)(height / 2));
graphics.DrawLine(&pen, (int)(width / 2 + width / 2 * std::cos(45)), height, (int)(width), (int)(height / 2));
graphics.DrawLine(&pen, (int)(width / 2 + width / 2 * std::cos(45)), 0, (int)(width / 2 + width / 2 * -std::cos(45)), 0);
graphics.DrawLine(&pen, (int)(width / 2 + width / 2 * std::cos(45)), (int)(height-1), (int)(width / 2 + width / 2 * -std::cos(45)), (int)(height)-1);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam) {
static int sw = 0;
POINT pt;
HMENU hmenu, hSubmenu;
HDC hdc;
PAINTSTRUCT ps;
static int width = 0, height = 0;
static int iXpos = 0, iYpos = 0;
RECT rect;
switch (message) {
case WM_MOVE:
iXpos = LOWORD(lParam);
iYpos = HIWORD(lParam);
case WM_SIZE:
width = LOWORD(lParam);
height = HIWORD(lParam);
break;
case WM_CREATE:
SetLayeredWindowAttributes(hwnd, RGB(255, 255, 255), 120, LWA_ALPHA);
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCLOSE:
DestroyWindow(hwnd);
break;
case ID_R_90:
InvalidateRect(hwnd, NULL, TRUE);
MoveWindow(hwnd, iXpos, iYpos, 778, 440, TRUE);
break;
case ID_R_100:
InvalidateRect(hwnd, NULL, TRUE);
MoveWindow(hwnd, iXpos, iYpos, 867, 480, TRUE);
break;
case ID_R_110:
InvalidateRect(hwnd, NULL, TRUE);
MoveWindow(hwnd, iXpos, iYpos, 955, 525, TRUE);
break;
case ID_R_125:
InvalidateRect(hwnd, NULL, TRUE);
MoveWindow(hwnd, iXpos, iYpos, 1084, 600, TRUE);
break;
case ID_R_150:
InvalidateRect(hwnd, NULL, TRUE);
MoveWindow(hwnd, iXpos, iYpos, 1300, 720, TRUE);
break;
default:
return (DefWindowProc(hwnd, message, wParam, lParam));
}
break;
case WM_RBUTTONDOWN:
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
hmenu = LoadMenu((HINSTANCE)GetWindowLong(hwnd,-6 ), MAKEINTRESOURCE(IDR_MENU1));
hSubmenu = GetSubMenu(hmenu, 0);
ClientToScreen(hwnd, &pt);
TrackPopupMenu(hSubmenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, NULL);
DestroyMenu(hmenu);
break;
case WM_LBUTTONDOWN:
PostMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam);
break;
case WM_PAINT:
GetClientRect(hwnd, &rect);
hdc = BeginPaint(hwnd, &ps);
OnPaint(hwnd, hdc, rect.bottom, rect.right);
EndPaint(hwnd, &ps);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
) {
HWND hWnd;
LPCTSTR szclassName = TEXT("GNT_Area_Cpp");
WNDCLASSEX wcex;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
ZeroMemory((LPVOID)&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName = TEXT("IDR_MENU1");
wcex.lpszClassName = szclassName;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
hWnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED, szclassName, 0, (WS_BORDER),
CW_USEDEFAULT, CW_USEDEFAULT,
867, 480,
NULL, NULL, hInstance, NULL);
SetWindowLong(hWnd, GWL_STYLE, 0);
ShowWindow(hWnd, SW_SHOW);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0) == 1) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gdiplusToken);
return msg.wParam;
}