Sorting Network Verify and Draw
Check Whether Comparator Networks Sort and Draw Them
WindowsHelpers.cpp
Go to the documentation of this file.
1
6
7// MIT License
8//
9// Copyright (c) 2022 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 "SortingNetwork.h"
35#include "resource.h"
36
40
41std::wstring FileNameBase(const std::wstring& wstrPath){
42 const size_t n0 = wstrPath.find_last_of(L"\\");
43
44 std::wstring wstrResult = (n0 == std::string::npos)? wstrPath:
45 wstrPath.substr(n0 + 1, wstrPath.size() - n0);
46
47 const size_t n1 = wstrResult.find_last_of(L".");
48
49 if(n1 != std::string::npos)
50 wstrResult = wstrResult.substr(0, n1);
51
52 return wstrResult;
53} //FileNameBase
54
62
63void MinDragRect(HWND hwnd, WPARAM wParam, RECT* pRect, int w, int h){
64 RECT cr; //client rectangle
65 RECT wr; //window rectangle, includes client rectangle and borders
66
67 GetClientRect(hwnd, &cr);
68 GetWindowRect(hwnd, &wr);
69
70 //combined border width and height
71
72 const int bw = (wr.right - wr.left) - (cr.right - cr.left); //border width
73 const int bh = (wr.bottom - wr.top) - (cr.bottom - cr.top); //border height
74
75 //new drag window width and height
76
77 const int dw = max(w, pRect->right - pRect->left - bw) + bw; //new width
78 const int dh = max(h, pRect->bottom - pRect->top - bh) + bh; //new height
79
80 //enforce new drag window width and height
81
82 switch(wParam){ //which edge are we dragging on?
83 case WMSZ_LEFT: //left edge
84 pRect->left = pRect->right - dw;
85 break;
86
87 case WMSZ_RIGHT: //right edge
88 pRect->right = pRect->left + dw;
89 break;
90
91 case WMSZ_TOP: //top edge
92 pRect->top = pRect->bottom - dh;
93 break;
94
95 case WMSZ_BOTTOM: //bottom edge
96 pRect->bottom = pRect->top + dh;
97 break;
98
99 case WMSZ_TOPRIGHT: //top right corner
100 pRect->top = pRect->bottom - dh;
101 pRect->right = pRect->left + dw;
102 break;
103
104 case WMSZ_TOPLEFT: //top left corner
105 pRect->top = pRect->bottom - dh;
106 pRect->left = pRect->right - dw;
107 break;
108
109 case WMSZ_BOTTOMRIGHT: //bottom right corner
110 pRect->bottom = pRect->top + dh;
111 pRect->right = pRect->left + dw;
112 break;
113
114 case WMSZ_BOTTOMLEFT: //bottom left corner
115 pRect->bottom = pRect->top + dh;
116 pRect->left = pRect->right - dw;
117 break;
118 } //switch
119} //MinDragRect
120
122// Initialization functions
123
124#pragma region Initialization
125
130
131void InitWindow(HINSTANCE hInst, INT nShow, WNDPROC WndProc){
132 const char appname[] = "Sorting Network Verify and Draw";
133
134 WNDCLASSEX wndClass = {0}; //extended window class structure
135
136 wndClass.cbSize = sizeof(WNDCLASSEX);
137 wndClass.style = CS_HREDRAW | CS_VREDRAW;
138 wndClass.lpfnWndProc = WndProc;
139 wndClass.cbClsExtra = 0;
140 wndClass.cbWndExtra = 0;
141 wndClass.hInstance = hInst;
142 wndClass.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
143 wndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
144 wndClass.hbrBackground = nullptr;
145 wndClass.lpszMenuName = nullptr;
146 wndClass.lpszClassName = appname;
147 wndClass.hIconSm = 0;
148
149 RegisterClassEx(&wndClass);
150
151 const DWORD dwStyle = WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX |
152 WS_THICKFRAME | WS_SYSMENU;
153 const DWORD dwStyleEx = WS_EX_APPWINDOW | WS_EX_DLGMODALFRAME;
154
155 const int w = 600; //window client area width.
156 const int h = 600; //window client area height.
157
158 RECT r;
159 r.left = 0; r.right = w;
160 r.top = 0; r.bottom = h + GetSystemMetrics(SM_CYMENU);
161 AdjustWindowRectEx(&r, dwStyle, FALSE, dwStyleEx);
162
163 const HWND hwnd = CreateWindowEx(dwStyleEx, appname, appname, dwStyle,
164 CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top,
165 nullptr, nullptr, hInst, nullptr);
166
167 ShowWindow(hwnd, nShow);
168 UpdateWindow(hwnd);
169} //InitWindow
170
173
174ULONG_PTR InitGDIPlus(){
175 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
176 ULONG_PTR gdiplusToken;
177 Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
178 return gdiplusToken;
179} //InitGDIPlus
180
181#pragma endregion Initialization
182
184// Save functions
185
186#pragma region Save
187
192
193HRESULT GetEncoderClsid(const WCHAR* format, CLSID* pClsid){
194 UINT num = 0; //number of image encoders
195 UINT n = 0; //size of the image encoder array in bytes
196 HRESULT hr = E_FAIL; //return result
197
198 Gdiplus::ImageCodecInfo* pCodecInfo = nullptr; //for codec info
199 if(FAILED(Gdiplus::GetImageEncodersSize(&num, &n)))return E_FAIL; //get sizes
200 if(n == 0)return E_FAIL; //there are no encoders
201
202 pCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(n)); //allocate codec info memory
203 if(pCodecInfo == nullptr)return E_FAIL; //malloc failed (as if)
204 if(FAILED(GetImageEncoders(num, n, pCodecInfo)))return E_FAIL; //get encoders
205
206 for(UINT j=0; j<num && hr!=S_OK; j++) //for each encoder, while not found
207 if(wcscmp(pCodecInfo[j].MimeType, format) == 0){ //found the codex we want
208 *pClsid = pCodecInfo[j].Clsid; //return it
209 hr = S_OK; //success
210 } //if
211
212 free(pCodecInfo); //clean up
213 return hr;
214} //GetEncoderClsid
215
224
225HRESULT ExportImage(const eExport t, HWND hwnd, CRenderableComparatorNet* pNet,
226 std::wstring& wstrName)
227{
228 COMDLG_FILTERSPEC filetypes[1];
229 std::wstring wstrTitle = L"Export "; //for dialog box title
230 std::wstring wstrDefaultExtension; //for dialog box default file extension
231
232 //set file types, title, and default extension for export type
233
234 switch(t){
235 case eExport::Png:
236 filetypes[0] = {L"PNG Files", L"*.png"};
237 wstrTitle += L"PNG"; wstrDefaultExtension = L"png";
238 break;
239
240 case eExport::Svg:
241 filetypes[0] = {L"SVG Files", L"*.svg"};
242 wstrTitle += L"SVG"; wstrDefaultExtension = L"svg";
243 break;
244
245 case eExport::TeX:
246 filetypes[0] = {L"TeX Files", L"*.tex"};
247 wstrTitle += L"TeX"; wstrDefaultExtension = L"tex";
248 break;
249 } //switch
250
251 wstrTitle += L" Image";
252
253 //prepare for the dialog box
254
255 CComPtr<IFileSaveDialog> pDlg; //pointer to save dialog box
256 CComPtr<IShellItem> pItem; //item pointer
257 LPWSTR pwsz = nullptr; //pointer to null-terminated wide string for result
258
259 //fire up the save dialog box
260
261 HRESULT hr = pDlg.CoCreateInstance(__uuidof(FileSaveDialog));
262
263 if(SUCCEEDED(hr)){
264 pDlg->SetFileTypes(_countof(filetypes), filetypes); //set file types
265 pDlg->SetTitle(wstrTitle.c_str()); //set title bar text
266 pDlg->SetFileName(wstrName.c_str()); //set default file name
267 pDlg->SetDefaultExtension(wstrDefaultExtension.c_str()); //set default extension
268
269 hr = pDlg->Show(hwnd); //show the dialog box
270
271 if(SUCCEEDED(hr)){
272 hr = pDlg->GetResult(&pItem); //get the result item
273
274 if(SUCCEEDED(hr)){
275 hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pwsz); //get file name
276
277 if(SUCCEEDED(hr)){
278 switch(t){ //here's where the export happens
279 case eExport::Png: hr = pNet->ExportToPNG(pwsz); break;
280 case eExport::Svg: hr = pNet->ExportToSVG(pwsz); break;
281 case eExport::TeX: hr = pNet->ExportToTex(pwsz); break;
282 } //switch
283
284 if(SUCCEEDED(hr))
285 wstrName = FileNameBase(std::wstring(pwsz)); //set file name
286 } //if
287 } //if
288 } //if
289 } //if
290
291 CoTaskMemFree(pwsz); //clean up
292
293 return hr;
294} //ExportImage
295
302
303HRESULT Load(HWND hwnd, CComparatorNetwork* pNet,
304 std::wstring& wstrName)
305{
306 COMDLG_FILTERSPEC filetypes[] = { //text files only
307 {L"TXT Files", L"*.txt"}
308 }; //filetypes
309
310 HRESULT hr = S_OK; //success or failure
311
312 CComPtr<IFileOpenDialog> pDlg; //pointer to save dialog box
313 CComPtr<IShellItem> pItem; //item pointer
314 LPWSTR pwsz = nullptr; //pointer to null-terminated wide string for result
315
316 hr = pDlg.CoCreateInstance(__uuidof(FileOpenDialog)); //fire up the Open dialog box
317
318 if(SUCCEEDED(hr)){
319 pDlg->SetFileTypes(_countof(filetypes), filetypes); //set file types
320 pDlg->SetTitle(L"Open Comparator Network"); //set title bar text
321 pDlg->SetDefaultExtension(L"txt"); //set default extension
322
323 hr = pDlg->Show(hwnd); //show the dialog box
324
325 if(SUCCEEDED(hr)){
326 hr = pDlg->GetResult(&pItem);
327
328 if(SUCCEEDED(hr))
329 hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pwsz);
330 } //if
331
332 if(SUCCEEDED(hr))
333 hr = pNet->Read(pwsz)? S_OK: E_FAIL; //read file into comparator network
334 } //if
335
336 if(SUCCEEDED(hr))
337 wstrName = FileNameBase(std::wstring(pwsz)); //set file name
338
339 CoTaskMemFree(pwsz); //clean up
340
341 return hr;
342} //Load
343
344#pragma endregion Save
345
347// Create menu functions
348
349#pragma region Create menu functions
350
353
354void CreateFileMenu(HMENU hParent){
355 HMENU hMenu = CreateMenu();
356
357 AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"Open...");
358 AppendMenuW(hMenu, MF_STRING, IDM_FILE_VERIFY, L"Verify...");
359 CreateExportMenu(hMenu); //create Export sub-menu
360 AppendMenuW(hMenu, MF_SEPARATOR, 0, nullptr);
361 AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"Quit");
362
363 AppendMenuW(hParent, MF_POPUP, (UINT_PTR)hMenu, L"&File");
364
365 EnableMenuItem(hMenu, IDM_FILE_EXPORT_PNG, MF_GRAYED);
366 EnableMenuItem(hMenu, IDM_FILE_EXPORT_TEX, MF_GRAYED);
367 EnableMenuItem(hMenu, IDM_FILE_EXPORT_SVG, MF_GRAYED);
368 EnableMenuItem(hMenu, IDM_FILE_VERIFY, MF_GRAYED);
369} //CreateFileMenu
370
373
374void CreateExportMenu(HMENU hParent){
375 HMENU hMenu = CreateMenu();
376
377 AppendMenuW(hMenu, MF_STRING, IDM_FILE_EXPORT_PNG, L"Png");
378 AppendMenuW(hMenu, MF_STRING, IDM_FILE_EXPORT_SVG, L"Svg");
379 AppendMenuW(hMenu, MF_STRING, IDM_FILE_EXPORT_TEX, L"TeX");
380
381 AppendMenuW(hParent, MF_POPUP, (UINT_PTR)hMenu, L"Export");
382} //CreateExportMenu
383
386
387void CreateGenerateMenu(HMENU hParent){
388 HMENU hMenu = CreateMenu();
389
390 AppendMenuW(hMenu, MF_STRING, IDM_GENERATE_MINBUBBLE, L"Bubblesort min");
391 AppendMenuW(hMenu, MF_STRING, IDM_GENERATE_MAXBUBBLE, L"Bubblesort max");
392 AppendMenuW(hMenu, MF_STRING, IDM_GENERATE_BUBBLE, L"Parallel bubblesort");
393 AppendMenuW(hMenu, MF_SEPARATOR, 0, nullptr);
394 AppendMenuW(hMenu, MF_STRING, IDM_GENERATE_ODDEVEN, L"Odd-even");
395 AppendMenuW(hMenu, MF_STRING, IDM_GENERATE_BITONIC, L"Bitonic");
396 AppendMenuW(hMenu, MF_SEPARATOR, 0, nullptr);
397 AppendMenuW(hMenu, MF_STRING, IDM_GENERATE_PAIRWISE, L"Pairwise");
398
399 AppendMenuW(hParent, MF_POPUP, (UINT_PTR)hMenu, L"Generate");
400} //CreateGenerateMenu
401
404
405void CreateViewMenu(HMENU hParent){
406 HMENU hMenu = CreateMenu();
407
408 AppendMenuW(hMenu, MF_STRING, IDM_VIEW_HORIZONTAL, L"Horizontal");
409 AppendMenuW(hMenu, MF_STRING, IDM_VIEW_VERTICAL, L"Vertical");
410
411 AppendMenuW(hParent, MF_POPUP, (UINT_PTR)hMenu, L"&View");
412} //CreateViewMenu
413
416
417void CreateHelpMenu(HMENU hParent){
418 HMENU hMenu = CreateMenu();
419
420 AppendMenuW(hMenu, MF_STRING, IDM_HELP_HELP, L"Display help...");
421 AppendMenuW(hMenu, MF_STRING, IDM_HELP_ABOUT, L"About...");
422 AppendMenuW(hParent, MF_POPUP, (UINT_PTR)hMenu, L"&Help");
423} //CreateHelpMenu
424
425#pragma endregion Create menu functions
eExport
Export type.
Definition: Defines.h:42
Useful includes.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Window procedure.
Definition: Main.cpp:53
Interface for the sorting network CSortingNetwork.
void MinDragRect(HWND hwnd, WPARAM wParam, RECT *pRect, int w, int h)
Enforce minimum drag rectangle.
void CreateFileMenu(HMENU hParent)
Create File menu.
HRESULT Load(HWND hwnd, CComparatorNetwork *pNet, std::wstring &wstrName)
Load comparator network.
void CreateExportMenu(HMENU hParent)
Create File menu.
std::wstring FileNameBase(const std::wstring &wstrPath)
HRESULT ExportImage(const eExport t, HWND hwnd, CRenderableComparatorNet *pNet, std::wstring &wstrName)
Export.
void CreateGenerateMenu(HMENU hParent)
Create Generate menu.
HRESULT GetEncoderClsid(const WCHAR *format, CLSID *pClsid)
Get encoder CLSID.
ULONG_PTR InitGDIPlus()
Initialize GDI+.
void CreateHelpMenu(HMENU hParent)
Create Help menu.
void InitWindow(HINSTANCE hInst, INT nShow, WNDPROC WndProc)
Initialize window.
void CreateViewMenu(HMENU hParent)
Create View menu.
Interface for some helpful Windows-specific functions.
#define IDM_GENERATE_MINBUBBLE
Menu id for Generate min-bubblesort.
#define IDM_GENERATE_MAXBUBBLE
Menu id for Generate max-bubblesort.
#define IDM_FILE_EXPORT_PNG
Menu id for Export PNG.
#define IDM_FILE_OPEN
Menu id for Generate.
#define IDM_GENERATE_BUBBLE
Menu id for Generate min-bubblesort.
#define IDM_GENERATE_BITONIC
Menu id for Generate bitonic.
#define IDM_FILE_VERIFY
Menu id for Verify.
#define IDM_FILE_QUIT
Menu id for Quit.
#define IDM_FILE_EXPORT_TEX
Menu id for Export TeX.
#define IDM_HELP_HELP
Menu id for display help.
#define IDM_VIEW_HORIZONTAL
Menu id for horizontal view.
#define IDM_FILE_EXPORT_SVG
Menu id for Export SVG.
#define IDM_GENERATE_PAIRWISE
Menu id for Generate pairwise.
#define IDM_VIEW_VERTICAL
Menu id for vertical view.
#define IDM_GENERATE_ODDEVEN
Menu id for Generate odd-even.
#define IDM_HELP_ABOUT
Menu id for display About info.
Comparator network.
virtual bool Read(LPWSTR)
Read from file.
Renderable comparator network.
HRESULT ExportToSVG(LPWSTR)
Export in SVG format.
HRESULT ExportToTex(LPWSTR)
Export in TeX format.
HRESULT ExportToPNG(LPWSTR)
Export in PNG format.