1
//-----------------------------------------------------------------------------
2
// Copyright 2008 Jonathan Westhues
4
// This file is part of SketchFlat.
6
// SketchFlat is free software: you can redistribute it and/or modify
7
// it under the terms of the GNU General Public License as published by
8
// the Free Software Foundation, either version 3 of the License, or
9
// (at your option) any later version.
11
// SketchFlat is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with SketchFlat. If not, see <http://www.gnu.org/licenses/>.
20
// Miscellaneous Win32-specific stuff, not specifically related to our main
23
// Jonathan Westhues, May 2007
24
//-----------------------------------------------------------------------------
25
#include "PreCompiled.h"
29
#define CREATE_MENU_TABLES
30
#include "sketchflat.h"
32
#include <Base/Console.h>
34
#define FREEZE_SUBKEY "SketchFlat"
42
extern BOOL EditingLayerListLabel;
44
// We'll keep these here because they get saved in the registry.
45
static BOOL ShowConstraints;
46
static BOOL ShowDatumItems;
47
static BOOL UseInches;
49
void CreateMainWindow(void);
50
void MakeMainWindowControls(void);
51
static BOOL ProcessKeyDown(int key);
53
static void UpdateMenusChecked(void);
55
//-----------------------------------------------------------------------------
56
// Entry point into the program.
57
//-----------------------------------------------------------------------------
58
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
59
LPSTR lpCmdLine, INT nCmdShow)
63
// This sets up the heap on which we will allocate our dynamic memory.
70
ThawWindowPos(MainWindow);
71
ShowConstraints = TRUE;
72
ShowDatumItems = TRUE;
73
UseInches = FALSE; ThawDWORD(UseInches);
75
MakeMainWindowControls();
76
ShowWindow(MainWindow, SW_SHOW);
79
// A file might be specified on the command line.
80
char loadFile[MAX_STRING] = "";
81
if(strlen(lpCmdLine) < MAX_STRING) {
83
while(isspace(*s)) s++;
87
s = strrchr(loadFile, '"');
94
while(ret = GetMessage(&msg, NULL, 0, 0)) {
95
// Don't let the tab control steal keyboard events.
96
if(msg.message == WM_KEYDOWN) {
97
if(ProcessKeyDown(msg.wParam)) continue;
99
// Even when the main window doesn't have the focus, let's give it
100
// the mousewheel events, with which to zoom.
101
if(msg.message == WM_MOUSEWHEEL) {
102
msg.hwnd = MainWindow;
105
TranslateMessage(&msg);
106
DispatchMessage(&msg);
109
FreezeWindowPos(MainWindow);
110
FreezeDWORD(UseInches);
120
//-----------------------------------------------------------------------------
121
// printf-like debug function, to the Windows debug log.
122
//-----------------------------------------------------------------------------
123
void dbp(char *str, ...)
127
sprintf(buf,"%5u: ", GetTickCount() % 100000);
130
_vsnprintf(buf+7, sizeof(buf)-100, str, f);
131
Base::Console().Log(buf);
132
Base::Console().Log("\n");
134
void dbp2(char *str, ...)
140
sprintf(buf,"%5u: ", GetTickCount() % 100000);
143
_vsnprintf(buf+7, sizeof(buf)-100, str, f);
144
Base::Console().Log(buf);
145
Base::Console().Log("\n");
148
//-----------------------------------------------------------------------------
149
// Is the shift key pressed?
150
//-----------------------------------------------------------------------------
151
BOOL uiShiftKeyDown(void)
153
//return !!(GetAsyncKeyState(VK_SHIFT) & 0x8000);
157
//-----------------------------------------------------------------------------
158
// Common dialog routines, to open or save a file.
159
//-----------------------------------------------------------------------------
160
BOOL uiGetOpenFile(char *file, char *defExtension, char *selPattern)
164
char tempSaveFile[MAX_PATH] = "";
166
memset(&ofn, 0, sizeof(ofn));
167
ofn.lStructSize = sizeof(ofn);
168
ofn.hInstance = Instance;
169
ofn.hwndOwner = MainWindow;
170
ofn.lpstrFilter = selPattern;
171
ofn.lpstrDefExt = defExtension;
172
ofn.lpstrFile = file;
173
ofn.nMaxFile = MAX_PATH;
174
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
176
EnableWindow(MainWindow, FALSE);
177
BOOL r = GetOpenFileName(&ofn);
178
EnableWindow(MainWindow, TRUE);
179
SetForegroundWindow(MainWindow);
183
BOOL uiGetSaveFile(char *file, char *defExtension, char *selPattern)
187
memset(&ofn, 0, sizeof(ofn));
188
ofn.lStructSize = sizeof(ofn);
189
ofn.hInstance = Instance;
190
ofn.hwndOwner = MainWindow;
191
ofn.lpstrFilter = selPattern;
192
ofn.lpstrDefExt = defExtension;
193
ofn.lpstrFile = file;
194
ofn.nMaxFile = MAX_PATH;
195
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
197
EnableWindow(MainWindow, FALSE);
198
BOOL r = GetSaveFileName(&ofn);
199
EnableWindow(MainWindow, TRUE);
200
SetForegroundWindow(MainWindow);
204
int uiSaveFileYesNoCancel(void)
206
/* return MessageBox(MainWindow,
207
"The program has changed since it was last saved.\r\n\r\n"
208
"Do you want to save the changes?", "SketchFlat",
209
MB_YESNOCANCEL | MB_ICONWARNING);*/
213
//-----------------------------------------------------------------------------
214
// For error messages to the user; printf-like, to a message box.
215
//-----------------------------------------------------------------------------
216
void uiError(char *str, ...)
221
vsprintf(buf, str, f);
223
Base::Console().Error(buf);
224
//HWND h = GetForegroundWindow();
225
//MessageBox(h, buf, "SketchFlat Error", MB_OK | MB_ICONERROR);
228
//-----------------------------------------------------------------------------
229
// Create a window with a given client area.
230
//-----------------------------------------------------------------------------
232
HWND CreateWindowClient(DWORD exStyle, char *className, char *windowName,
233
DWORD style, int x, int y, int width, int height, HWND parent,
234
HMENU menu, HINSTANCE instance, void *param)
236
// HWND h = CreateWindowEx(exStyle, className, windowName, style, x, y,
237
// width, height, parent, menu, instance, param);
240
// GetClientRect(h, &r);
241
// width = width - (r.right - width);
242
// height = height - (r.bottom - height);
244
// SetWindowPos(h, HWND_TOP, x, y, width, height, 0);
251
//-----------------------------------------------------------------------------
252
// Memory allocation functions. We'll use a Windows heap, which makes it
253
// easy to free everything when we're asked to.
254
//-----------------------------------------------------------------------------
255
//static HANDLE Heap;
256
void *Alloc(int bytes)
258
/* void *v = HeapAlloc(Heap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, bytes);
261
return malloc(bytes);
265
//HeapFree(Heap, HEAP_NO_SERIALIZE, p);
271
// HeapDestroy(Heap);
274
//Heap = HeapCreate(HEAP_NO_SERIALIZE, 1024*1024*20, 0);
277
//-----------------------------------------------------------------------------
278
// A separate allocator, that we use for polygons and such. This needs to
279
// be separate so the its stuff doesn't get freed when we free all the
280
// expression stuff at once.
281
//-----------------------------------------------------------------------------
286
void *DAlloc(int bytes)
288
return malloc(bytes);
291
//-----------------------------------------------------------------------------
292
// Routines to show and un-show the hourglass cursor. We use this when the
293
// solution routines are slow.
294
//-----------------------------------------------------------------------------
295
void uiSetCursorToHourglass(void)
297
//SetCursor(LoadCursor(0, IDC_WAIT));
299
void uiRestoreCursor(void)
303
//SetCursorPos(p.x, p.y);
307
//-----------------------------------------------------------------------------
308
// Create the menu bar associated with the main window. This changes,
309
// depending on whether we are are in the CAD or CAM view.
310
//-----------------------------------------------------------------------------
311
HMENU MakeMainWindowMenus(void)
313
HMENU top = CreateMenu();
319
for(i = 0; i < arraylen(Menus); i++) {
320
if(Menus[i].level == 0) {
322
AppendMenu(top, MF_STRING | MF_POPUP, (UINT_PTR)m, Menus[i].label);
324
if(subMenu >= arraylen(SubMenus)) oops();
325
SubMenus[subMenu] = m;
329
AppendMenu(m, MF_STRING, Menus[i].id, Menus[i].label);
331
AppendMenu(m, MF_SEPARATOR, Menus[i].id, "");
339
void uiCheckMenuById(int id, BOOL checked)
344
for(i = 0; i < arraylen(Menus); i++) {
345
if(Menus[i].level == 0) {
349
if(Menus[i].id == id) {
350
if(subMenu < 0) oops();
351
if(subMenu >= arraylen(SubMenus)) oops();
353
CheckMenuItem(SubMenus[subMenu], id,
354
checked ? MF_CHECKED : MF_UNCHECKED);
360
void uiEnableMenuById(int id, BOOL enabled)
365
for(i = 0; i < arraylen(Menus); i++) {
366
if(Menus[i].level == 0) {
370
if(Menus[i].id == id) {
371
if(subMenu < 0) oops();
372
if(subMenu >= arraylen(SubMenus)) oops();
374
EnableMenuItem(SubMenus[subMenu], id,
375
enabled ? MF_ENABLED : MF_GRAYED);
383
//-----------------------------------------------------------------------------
384
// Process a menu selection. We have a table, so just look through there
385
// and call the appropriate function.
386
//-----------------------------------------------------------------------------
387
void ProcessMenu(int id)
389
//if(id == 0) return;
392
//for(i = 0; i < arraylen(Menus); i++) {
393
// if(Menus[i].id == id) {
394
// // If e.g. we're dragging something in the sketch mode GUI, then
396
// CancelSketchModeOperation();
397
// (*(Menus[i].fn))(id);
404
//-----------------------------------------------------------------------------
405
// Process a keypress. If the keypress came to the main window, then it's
406
// probably an accelerator for a menu item. Not an error if it's not
407
// meaningful, though.
408
//-----------------------------------------------------------------------------
409
static BOOL IsForNavigation(int key)
411
/* return (key == VK_LEFT ||
418
static BOOL ProcessKeyDown(int key)
422
//// There's a textbox that we place on the drawing, to enter the values
423
//// of dimensions. When it's visible, it should get keys.
424
//if(uiTextEntryBoxIsVisible()) {
425
// if((key >= '0' && key <= '9') || key == VK_OEM_MINUS ||
426
// (key >= VK_NUMPAD0 && key <= VK_NUMPAD9) ||
427
// key == VK_SUBTRACT ||
428
// key == VK_DECIMAL ||
429
// key == VK_OEM_PERIOD || IsForNavigation(key))
435
//// The labels in the list of sketches/layers are editable. When that
436
//// textbox is shown, it should get keys.
437
//if(EditingLayerListLabel) {
438
// if((key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9') ||
439
// key == VK_OEM_MINUS ||
440
// IsForNavigation(key) || key == VK_RETURN || key == VK_ESCAPE)
444
// // Swallow additional keys; they probably don't want to use
445
// // menu accelerators while editing the label.
450
//// These ones are useful to navigate the "consistency lists" in the
451
//// right-side toolbar.
452
//if(key == VK_LEFT || key == VK_RIGHT || key == VK_UP || key == VK_DOWN) {
457
//if(GetAsyncKeyState(VK_CONTROL) & 0x8000) {
458
// if(key >= 'A' && key <= 'Z') {
459
// // Map the control characters appropriately.
466
//for(i = 0; i < arraylen(Menus); i++) {
467
// if(Menus[i].level == 0) {
471
// if(Menus[i].accelerator == key) {
472
// // We don't want the keyboard shortcut to work when the menu is
474
// if(EnableMenuItem(SubMenus[subMenu], Menus[i].id, MF_ENABLED) ==
477
// // If e.g. we're dragging something in the sketch mode GUI,
478
// // then stop that.
479
// CancelSketchModeOperation();
480
// (*(Menus[i].fn))(Menus[i].id);
483
// // We just accidentally enabled a disabled menu item, so
484
// // fix that. I'm not sure how to query the state without
486
// EnableMenuItem(SubMenus[subMenu], Menus[i].id, MF_GRAYED);
491
//// Otherwise no harm, though; pass it along to the general-purpose
492
//// keypress handler.
497
//-----------------------------------------------------------------------------
498
// Selections that get saved in the registry, and are therefore easiest
499
// to store with the Win32 stuff.
500
//-----------------------------------------------------------------------------
501
static void UpdateMenusChecked(void)
503
uiCheckMenuById(MNU_VIEW_SHOW_CONSTRAINTS, ShowConstraints);
504
uiCheckMenuById(MNU_VIEW_SHOW_DATUM_ITEMS, ShowDatumItems);
505
uiCheckMenuById(MNU_VIEW_IN_INCHES, UseInches);
506
uiCheckMenuById(MNU_VIEW_IN_MM, !UseInches);
508
void MenuSettings(int id)
511
case MNU_VIEW_SHOW_CONSTRAINTS:
512
ShowConstraints = !ShowConstraints;
515
case MNU_VIEW_SHOW_DATUM_ITEMS:
516
ShowDatumItems = !ShowDatumItems;
519
case MNU_VIEW_IN_INCHES:
521
UpdateAfterUnitChange();
526
UpdateAfterUnitChange();
530
UpdateMenusChecked();
533
BOOL uiShowConstraints(void) { return ShowConstraints; }
534
BOOL uiShowDatumItems(void) { return ShowDatumItems; }
535
BOOL uiUseInches(void) { return UseInches; }