diff options
| author | Pietro Gagliardi <[email protected]> | 2014-08-26 12:52:32 -0400 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-08-26 12:52:32 -0400 |
| commit | adbe5303e7d97e439e1f1f75df23d357b037f702 (patch) | |
| tree | a9bafa99c1def93cae7afc54c3f2679445b3c0f5 /redo/dialog_windows.c | |
| parent | e7490ce49b113f4d1877de8f5ee4b40b183fbabf (diff) | |
Changed the way dialogs work so that they do real modality properly and implemented such on Windows.
Diffstat (limited to 'redo/dialog_windows.c')
| -rw-r--r-- | redo/dialog_windows.c | 87 |
1 files changed, 37 insertions, 50 deletions
diff --git a/redo/dialog_windows.c b/redo/dialog_windows.c index ad48cd5..10fb75c 100644 --- a/redo/dialog_windows.c +++ b/redo/dialog_windows.c @@ -3,73 +3,60 @@ #include "winapi_windows.h" #include "_cgo_export.h" -static LRESULT CALLBACK dialogSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data) -{ - switch (uMsg) { - case WM_COMMAND: - // we must re-enable other windows in the right order (see http://blogs.msdn.com/b/oldnewthing/archive/2004/02/27/81155.aspx) - // see http://stackoverflow.com/questions/25494914/is-there-something-like-cdn-filecancel-analogous-to-cdn-fileok-for-getting-when - if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) - SendMessageW(msgwin, msgEndModal, 0, 0); - break; // let the dialog handle it now - case WM_NCDESTROY: - if ((*fv_RemoveWindowSubclass)(hwnd, dialogSubProc, id) == FALSE) - xpanic("error removing dialog subclass (which was for its own event handler)", GetLastError()); - } - return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam); -} - // this should be reasonable #define NFILENAME 4096 -static UINT_PTR CALLBACK openSaveFileHook(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_INITDIALOG) { - HWND parent; - - parent = GetParent(hwnd); - if (parent == NULL) - xpanic("error gettign parent of OpenFile() dialog for event handling", GetLastError()); - if ((*fv_SetWindowSubclass)(parent, dialogSubProc, 0, (DWORD_PTR) NULL) == FALSE) - xpanic("error subclassing OpenFile() dialog to give it its own event handler", GetLastError()); - } else if (uMsg == WM_NOTIFY) { - OFNOTIFY *of = (OFNOTIFY *) lParam; - - if (of->hdr.code == CDN_FILEOK) - SendMessageW(msgwin, msgEndModal, 0, 0); - } - return 0; -} +struct openFileData { + HWND parent; + void *f; + WCHAR *filenameBuffer; +}; -WCHAR *openFile(void) +static DWORD WINAPI doOpenFile(LPVOID data) { + struct openFileData *o = (struct openFileData *) data; OPENFILENAMEW ofn; DWORD err; - WCHAR *filenameBuffer; - // freed on the Go side - filenameBuffer = (WCHAR *) malloc((NFILENAME + 1) * sizeof (WCHAR)); - if (filenameBuffer == NULL) - xpanic("memory exhausted in OpenFile()", GetLastError()); - filenameBuffer[0] = L'\0'; // required by GetOpenFileName() to indicate no previous filename + o->filenameBuffer[0] = L'\0'; // required by GetOpenFileName() to indicate no previous filename ZeroMemory(&ofn, sizeof (OPENFILENAMEW)); ofn.lStructSize = sizeof (OPENFILENAMEW); - ofn.hwndOwner = NULL; + ofn.hwndOwner = o->parent; ofn.hInstance = hInstance; ofn.lpstrFilter = NULL; // no filters - ofn.lpstrFile = filenameBuffer; + ofn.lpstrFile = o->filenameBuffer; ofn.nMaxFile = NFILENAME + 1; // TODO include + 1? ofn.lpstrInitialDir = NULL; // let system decide ofn.lpstrTitle = NULL; // let system decide // TODO OFN_SHAREAWARE? - ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_FORCESHOWHIDDEN | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR | OFN_NODEREFERENCELINKS | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST; - ofn.lpfnHook = openSaveFileHook; - SendMessageW(msgwin, msgBeginModal, 0, 0); + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_FORCESHOWHIDDEN | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR | OFN_NODEREFERENCELINKS | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST; if (GetOpenFileNameW(&ofn) == FALSE) { err = CommDlgExtendedError(); - if (err == 0) // user cancelled - return NULL; - xpaniccomdlg("error running open file dialog", err); + if (err != 0) // user cancelled + xpaniccomdlg("error running open file dialog", err); + free(o->filenameBuffer); // free now so we can set it to NULL without leaking + o->filenameBuffer = NULL; } - return filenameBuffer; + if (PostMessageW(msgwin, msgOpenFileDone, (WPARAM) (o->filenameBuffer), (LPARAM) (o->f)) == 0) + xpanic("error posting OpenFile() finished message to message-only window", GetLastError()); + free(o); // won't free o->f or o->filenameBuffer in above invocation + return 0; +} + +void openFile(HWND hwnd, void *f) +{ + struct openFileData *o; + + // freed by the thread + o = (struct openFileData *) malloc(sizeof (struct openFileData)); + if (o == NULL) + xpanic("memory exhausted allocating data structure in OpenFile()", GetLastError()); + o->parent = hwnd; + o->f = f; + // freed on the Go side + o->filenameBuffer = (WCHAR *) malloc((NFILENAME + 1) * sizeof (WCHAR)); + if (o->filenameBuffer == NULL) + xpanic("memory exhausted allocating filename buffer in OpenFile()", GetLastError()); + if (CreateThread(NULL, 0, doOpenFile, (LPVOID) o, 0, NULL) == NULL) + xpanic("error creating thread for running OpenFIle()", GetLastError()); } |
