Wang Tiling
A Simple Wang Tiling Generator
WindowsHelpers.cpp
Go to the documentation of this file.
1
6
7// MIT License
8//
9// Copyright (c) 2020 Ian Parberry
10//
11// Permission is hereby granted, free of charge, to any person obtaining a copy
12// of this software and associated documentation files (the "Software"), to
13// deal in the Software without restriction, including without limitation the
14// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
15// sell copies of the Software, and to permit persons to whom the Software is
16// furnished to do so, subject to the following conditions:
17//
18// The above copyright notice and this permission notice shall be included in
19// all copies or substantial portions of the Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27// IN THE SOFTWARE.
28
29#include <shobjidl_core.h>
30#include <atlbase.h>
31
32#include "WindowsHelpers.h"
33#include "Includes.h"
34#include "resource.h"
35
37// Initialization functions
38
39#pragma region Initialization
40
45
46void InitWindow(HINSTANCE hInst, INT nShow, WNDPROC WndProc){
47 const char appname[] = "WangTiler";
48
49 WNDCLASSEX wndClass = {0}; //extended window class structure
50
51 wndClass.cbSize = sizeof(WNDCLASSEX);
52 wndClass.style = CS_HREDRAW | CS_VREDRAW;
53 wndClass.lpfnWndProc = WndProc;
54 wndClass.cbClsExtra = 0;
55 wndClass.cbWndExtra = 0;
56 wndClass.hInstance = hInst;
57 wndClass.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
58 wndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
59 wndClass.hbrBackground = nullptr;
60 wndClass.lpszMenuName = nullptr;
61 wndClass.lpszClassName = appname;
62 wndClass.hIconSm = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON2));
63
64 RegisterClassEx(&wndClass);
65
66 const DWORD dwStyle = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
67 const DWORD dwStyleEx = WS_EX_APPWINDOW | WS_EX_DLGMODALFRAME;
68
69 const int w = 600; //window client area width.
70 const int h = 600; //window client area height.
71
72 RECT r;
73 r.left = 0; r.right = w;
74 r.top = 0; r.bottom = h + GetSystemMetrics(SM_CYMENU);
75 AdjustWindowRectEx(&r, dwStyle, FALSE, dwStyleEx);
76
77 const HWND hwnd = CreateWindowEx(dwStyleEx, appname, appname, dwStyle,
78 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top,
79 nullptr, nullptr, hInst, nullptr);
80
81 ShowWindow(hwnd, nShow);
82 UpdateWindow(hwnd);
83} //InitWindow
84
87
88ULONG_PTR InitGDIPlus(){
89 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
90 ULONG_PTR gdiplusToken;
91 Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
92 return gdiplusToken;
93} //InitGDIPlus
94
95#pragma endregion Initialization
96
98// Save functions
99
100#pragma region Save
101
106
107HRESULT GetEncoderClsid(const WCHAR* format, CLSID* pClsid){
108 UINT num = 0; //number of image encoders
109 UINT n = 0; //size of the image encoder array in bytes
110 HRESULT hr = E_FAIL; //return result
111
112 Gdiplus::ImageCodecInfo* pCodecInfo = nullptr; //for codec info
113 if(FAILED(Gdiplus::GetImageEncodersSize(&num, &n)))return E_FAIL; //get sizes
114 if(n == 0)return E_FAIL; //there are no encoders
115
116 pCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(n)); //allocate codec info memory
117 if(pCodecInfo == nullptr)return E_FAIL; //malloc failed (as if)
118 if(FAILED(GetImageEncoders(num, n, pCodecInfo)))return E_FAIL; //get encoders
119
120 for(UINT j=0; j<num && hr!=S_OK; j++) //for each encoder, while not found
121 if(wcscmp(pCodecInfo[j].MimeType, format) == 0){ //found the codex we want
122 *pClsid = pCodecInfo[j].Clsid; //return it
123 hr = S_OK; //success
124 } //if
125
126 free(pCodecInfo); //clean up
127 return hr;
128} //GetEncoderClsid
129
140
141HRESULT SaveBitmap(HWND hwnd, Gdiplus::Bitmap* pBitmap){
142 COMDLG_FILTERSPEC filetypes[] = { //png files only
143 {L"PNG Files", L"*.png"}
144 }; //filetypes
145
146 std::wstring wstrFileName; //result
147 CComPtr<IFileSaveDialog> pDlg; //pointer to save dialog box
148 static int n = 0; //number of images saved in this run
149 std::wstring wstrName = L"Image" + std::to_wstring(n++); //default file name
150 CComPtr<IShellItem> pItem; //item pointer
151 LPWSTR pwsz = nullptr; //pointer to null-terminated wide string for result
152
153 //fire up the save dialog box
154
155 if(FAILED(pDlg.CoCreateInstance(__uuidof(FileSaveDialog))))return E_FAIL;
156
157 pDlg->SetFileTypes(_countof(filetypes), filetypes); //set file types to png
158 pDlg->SetTitle(L"Save Image"); //set title bar text
159 pDlg->SetFileName(wstrName.c_str()); //set default file name
160 pDlg->SetDefaultExtension(L"png"); //set default extension
161
162 if(FAILED(pDlg->Show(hwnd)))return E_FAIL; //show the dialog box
163 if(FAILED(pDlg->GetResult(&pItem)))return E_FAIL; //get the result item
164 if(FAILED(pItem->GetDisplayName(SIGDN_FILESYSPATH, &pwsz)))return E_FAIL; //get file name
165
166 //wstrFileName should now contain the selected file name
167
168 CLSID clsid; //for PNG class id
169 if(FAILED(GetEncoderClsid((WCHAR*)L"image/png", &clsid)))return E_FAIL; //get
170 pBitmap->Save(pwsz, &clsid, nullptr); //the actual save happens here
171
172 CoTaskMemFree(pwsz); //clean up
173
174 return S_OK;
175} //SaveBitmap
176
177#pragma endregion Save
178
180// Create menu functions
181
182#pragma region Create menu functions
183
186
187void CreateFileMenu(HMENU hParent){
188 HMENU hMenu = CreateMenu();
189
190 AppendMenuW(hMenu, MF_STRING, IDM_FILE_GENERATE, L"Generate");
191 AppendMenuW(hMenu, MF_STRING, IDM_FILE_SAVE, L"Save...");
192 AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"Quit");
193
194 AppendMenuW(hParent, MF_POPUP, (UINT_PTR)hMenu, L"&File");
195} //CreateFileMenu
196
200
201HMENU CreateTilesetMenu(HMENU hParent){
202 HMENU hMenu = CreateMenu();
203
204 AppendMenuW(hMenu, MF_STRING, IDM_TILESET_DEFAULT, L"Default");
205 AppendMenuW(hMenu, MF_STRING, IDM_TILESET_FLOWER, L"Flowers");
206 AppendMenuW(hMenu, MF_STRING, IDM_TILESET_MUD, L"Mud");
207 AppendMenuW(hMenu, MF_STRING, IDM_TILESET_GRASS, L"Grass");
208
209 AppendMenuW(hParent, MF_POPUP, (UINT_PTR)hMenu, L"&Tileset");
210 return hMenu;
211} //CreateTilesetMenu
212
215
216void CreateHelpMenu(HMENU hParent){
217 HMENU hMenu = CreateMenu();
218
219 AppendMenuW(hMenu, MF_STRING, IDM_HELP_HELP, L"Display help...");
220 AppendMenuW(hMenu, MF_STRING, IDM_HELP_ABOUT, L"About...");
221 AppendMenuW(hParent, MF_POPUP, (UINT_PTR)hMenu, L"&Help");
222} //CreateHelpMenu
223
224#pragma endregion Create menu functions
Useful includes.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Window procedure.
Definition: Main.cpp:41
HMENU CreateTilesetMenu(HMENU hParent)
Create Tileset menu.
void CreateFileMenu(HMENU hParent)
Create File menu.
HRESULT GetEncoderClsid(const WCHAR *format, CLSID *pClsid)
ULONG_PTR InitGDIPlus()
Initialize GDI+.
void CreateHelpMenu(HMENU hParent)
Create Help menu.
HRESULT SaveBitmap(HWND hwnd, Gdiplus::Bitmap *pBitmap)
Save bitmap to file.
void InitWindow(HINSTANCE hInst, INT nShow, WNDPROC WndProc)
Initialize window.
Interface for some helpful Windows-specific functions.
#define IDM_TILESET_FLOWER
Menu id for flower tileset.
#define IDM_FILE_SAVE
Menu id for Save.
#define IDM_TILESET_GRASS
Menu id for grass tileset.
#define IDM_FILE_QUIT
Menu id for Quit.
#define IDM_FILE_GENERATE
Menu id for Generate.
#define IDM_HELP_HELP
Menu id for display help.
#define IDM_TILESET_MUD
Menu id for dirt tileset.
#define IDM_HELP_ABOUT
Menu id for display About info.
#define IDM_TILESET_DEFAULT
Menu id for default tileset.