int SWELL_DialogBox(SWELL_DialogResourceIndex *reshead, const char *resid, HWND parent, DLGPROC dlgproc, LPARAM param) { SWELL_DialogResourceIndex *p=resById(reshead,resid); if (resid) // allow modal dialogs to be created without template { if (!p||(p->windowTypeFlags&SWELL_DLG_WS_CHILD)) return -1; } int ret=-1; HWND hwnd = SWELL_CreateDialog(reshead,resid,parent,dlgproc,param); // create dialog if (hwnd) { ReleaseCapture(); // force end of any captures WDL_PtrList<HWND__> enwnds; extern HWND__ *SWELL_topwindows; HWND a = SWELL_topwindows; while (a) { if (a->m_enabled && a != hwnd) { EnableWindow(a,FALSE); enwnds.Add(a); } a = a->m_next; } modalDlgRet r = { hwnd,false, -1 }; s_modalDialogs.Add(&r); ShowWindow(hwnd,SW_SHOW); while (s_modalDialogs.Find(&r)>=0 && !r.has_ret) { void SWELL_RunMessageLoop(); SWELL_RunMessageLoop(); Sleep(10); } ret=r.ret; s_modalDialogs.Delete(s_modalDialogs.Find(&r)); a = SWELL_topwindows; while (a) { if (!a->m_enabled && a != hwnd && enwnds.Find(a)>=0) EnableWindow(a,TRUE); a = a->m_next; } } // while in list, do something return ret; }
static LRESULT WINAPI swellFileSelectProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: if (lParam) // swell-specific { SetWindowLong(hwnd,GWL_WNDPROC,(LPARAM)SwellDialogDefaultWindowProc); SetWindowLong(hwnd,DWL_DLGPROC,(LPARAM)swellFileSelectProc); SetWindowLongPtr(hwnd,GWLP_USERDATA,lParam); BrowseFile_State *parms = (BrowseFile_State *)lParam; if (parms->caption) SetWindowText(hwnd,parms->caption); SWELL_MakeSetCurParms(1,1,0,0,hwnd,false,false); SWELL_MakeButton(0, parms->mode == BrowseFile_State::OPENDIR ? "Choose directory" : parms->mode == BrowseFile_State::SAVE ? "Save" : "Open", IDOK,0,0,0,0, 0); SWELL_MakeButton(0, "Cancel", IDCANCEL,0,0,0,0, 0); HWND edit = SWELL_MakeEditField(0x100, 0,0,0,0, 0); if (edit) { if (parms->initialfile && *parms->initialfile) SetWindowText(edit,parms->initialfile); else if (parms->initialdir && *parms->initialdir) { char buf[1024]; lstrcpyn_safe(buf,parms->initialdir,sizeof(buf) - 1); if (parms->mode != BrowseFile_State::OPENDIR && buf[0] && buf[strlen(buf)-1]!='/') lstrcatn(buf,"/",sizeof(buf)); SetWindowText(edit,buf); } } SWELL_MakeLabel(-1,parms->mode == BrowseFile_State::OPENDIR ? "Directory: " : "File:",0x101, 0,0,0,0, 0); if (BFSF_Templ_dlgid && BFSF_Templ_dlgproc) { HWND dlg = SWELL_CreateDialog(BFSF_Templ_reshead, BFSF_Templ_dlgid, hwnd, BFSF_Templ_dlgproc, 0); if (dlg) SetWindowLong(dlg,GWL_ID,0x102); BFSF_Templ_dlgproc=0; BFSF_Templ_dlgid=0; } SWELL_MakeSetCurParms(1,1,0,0,NULL,false,false); SetWindowPos(hwnd,NULL,0,0,600, 400, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE); } break; case WM_GETMINMAXINFO: { LPMINMAXINFO p=(LPMINMAXINFO)lParam; p->ptMinTrackSize.x = 300; p->ptMinTrackSize.y = 300; } break; case WM_SIZE: { BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA); // reposition controls RECT r; GetClientRect(hwnd,&r); const int buth = 24, cancelbutw = 50, okbutw = parms->mode == BrowseFile_State::OPENDIR ? 120 : 50; const int xborder = 4, yborder=8; const int fnh = 20, fnlblw = parms->mode == BrowseFile_State::OPENDIR ? 70 : 50; int ypos = r.bottom - 4 - buth; int xpos = r.right; SetWindowPos(GetDlgItem(hwnd,IDCANCEL), NULL, xpos -= cancelbutw + xborder, ypos, cancelbutw,buth, SWP_NOZORDER|SWP_NOACTIVATE); SetWindowPos(GetDlgItem(hwnd,IDOK), NULL, xpos -= okbutw + xborder, ypos, okbutw,buth, SWP_NOZORDER|SWP_NOACTIVATE); HWND emb = GetDlgItem(hwnd,0x102); if (emb) { RECT sr; GetClientRect(emb,&sr); if (ypos > r.bottom-4-sr.bottom) ypos = r.bottom-4-sr.bottom; SetWindowPos(emb,NULL, xborder,ypos, xpos - xborder*2, sr.bottom, SWP_NOZORDER|SWP_NOACTIVATE); ShowWindow(emb,SW_SHOWNA); } SetWindowPos(GetDlgItem(hwnd,0x100), NULL, xborder*2 + fnlblw, ypos -= fnh + yborder, r.right-fnlblw-xborder*3, fnh, SWP_NOZORDER|SWP_NOACTIVATE); SetWindowPos(GetDlgItem(hwnd,0x101), NULL, xborder, ypos, fnlblw, fnh, SWP_NOZORDER|SWP_NOACTIVATE); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwnd,0); return 0; case IDOK: { char buf[1024],msg[2048]; GetDlgItemText(hwnd,0x100,buf,sizeof(buf)); BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA); switch (parms->mode) { case BrowseFile_State::SAVE: if (!buf[0]) { MessageBox(hwnd,"No file specified","Error",MB_OK); return 0; } else { struct stat st={0,}; DIR *dir = opendir(buf); if (dir) { closedir(dir); snprintf(msg,sizeof(msg),"Path is a directory:\r\n\r\n%s",buf); MessageBox(hwnd,msg,"Invalid file",MB_OK); return 0; } if (!stat(buf,&st)) { snprintf(msg,sizeof(msg),"File exists:\r\n\r\n%s\r\n\r\nOverwrite?",buf); if (MessageBox(hwnd,msg,"Overwrite file?",MB_OKCANCEL)==IDCANCEL) return 0; } } break; case BrowseFile_State::OPENDIR: if (!buf[0]) { MessageBox(hwnd,"No directory specified","Error",MB_OK); return 0; } else { DIR *dir = opendir(buf); if (!dir) { snprintf(msg,sizeof(msg),"Error opening directory:\r\n\r\n%s\r\n\r\nCreate?",buf); if (MessageBox(hwnd,msg,"Create directory?",MB_OKCANCEL)==IDCANCEL) return 0; CreateDirectory(buf,NULL); dir=opendir(buf); if (!dir) { MessageBox(hwnd,"Error creating directory","Error",MB_OK); return 0; } } if (dir) closedir(dir); } break; default: if (!buf[0]) { MessageBox(hwnd,"No file specified","Error",MB_OK); return 0; } else { struct stat st={0,}; DIR *dir = opendir(buf); if (dir) { closedir(dir); snprintf(msg,sizeof(msg),"Path is a directory:\r\n\r\n%s",buf); MessageBox(hwnd,msg,"Invalid file",MB_OK); return 0; } if (stat(buf,&st)) { snprintf(msg,sizeof(msg),"File does not exist:\r\n\r\n%s",buf); MessageBox(hwnd,msg,"File not found",MB_OK); return 0; } } break; } if (parms->fnout) { lstrcpyn_safe(parms->fnout,buf,parms->fnout_sz); } else { size_t l = strlen(buf); parms->fnout = (char*)calloc(l+2,1); memcpy(parms->fnout,buf,l); } } EndDialog(hwnd,1); return 0; } break; } return 0; }
static LRESULT WINAPI swellFileSelectProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { const int maxPathLen = 2048; const char *multiple_files = "(multiple files)"; switch (uMsg) { case WM_CREATE: if (lParam) // swell-specific { SetWindowLong(hwnd,GWL_WNDPROC,(LPARAM)SwellDialogDefaultWindowProc); SetWindowLong(hwnd,DWL_DLGPROC,(LPARAM)swellFileSelectProc); SetWindowLongPtr(hwnd,GWLP_USERDATA,lParam); BrowseFile_State *parms = (BrowseFile_State *)lParam; if (parms->caption) SetWindowText(hwnd,parms->caption); SWELL_MakeSetCurParms(1,1,0,0,hwnd,false,false); SWELL_MakeButton(0, parms->mode == BrowseFile_State::OPENDIR ? "Choose directory" : parms->mode == BrowseFile_State::SAVE ? "Save" : "Open", IDOK,0,0,0,0, 0); SWELL_MakeButton(0, "Cancel", IDCANCEL,0,0,0,0, 0); HWND edit = SWELL_MakeEditField(0x100, 0,0,0,0, 0); HWND dir = SWELL_MakeCombo(0x103, 0,0,0,0, CBS_DROPDOWNLIST); HWND list = SWELL_MakeControl("",0x104,"SysListView32",LVS_REPORT|LVS_SHOWSELALWAYS| (parms->mode == BrowseFile_State::OPENMULTI ? 0 : LVS_SINGLESEL)| LVS_OWNERDATA|WS_BORDER|WS_TABSTOP,0,0,0,0,0); if (list) { LVCOLUMN c={LVCF_TEXT|LVCF_WIDTH, 0, 280, (char*)"Filename" }; ListView_InsertColumn(list,0,&c); c.cx = 120; c.pszText = (char*) "Size"; ListView_InsertColumn(list,1,&c); c.cx = 140; c.pszText = (char*) "Date"; ListView_InsertColumn(list,2,&c); } HWND extlist = (parms->extlist && *parms->extlist) ? SWELL_MakeCombo(0x105, 0,0,0,0, CBS_DROPDOWNLIST) : NULL; if (extlist) { const char *p = parms->extlist; while (*p) { const char *rd=p; p += strlen(p)+1; if (!*p) break; int a = SendMessage(extlist,CB_ADDSTRING,0,(LPARAM)rd); SendMessage(extlist,CB_SETITEMDATA,a,(LPARAM)p); p += strlen(p)+1; } SendMessage(extlist,CB_SETCURSEL,0,0); } SWELL_MakeLabel(-1,parms->mode == BrowseFile_State::OPENDIR ? "Directory: " : "File:",0x101, 0,0,0,0, 0); if (BFSF_Templ_dlgid && BFSF_Templ_dlgproc) { HWND dlg = SWELL_CreateDialog(BFSF_Templ_reshead, BFSF_Templ_dlgid, hwnd, BFSF_Templ_dlgproc, 0); if (dlg) SetWindowLong(dlg,GWL_ID,0x102); BFSF_Templ_dlgproc=0; BFSF_Templ_dlgid=0; } SWELL_MakeSetCurParms(1,1,0,0,NULL,false,false); if (edit && dir) { char buf[maxPathLen]; const char *filepart = ""; if (parms->initialfile && *parms->initialfile && *parms->initialfile != '.') { lstrcpyn_safe(buf,parms->initialfile,sizeof(buf)); char *p = (char *)WDL_get_filepart(buf); if (p > buf) { p[-1]=0; filepart = p; } } else if (parms->initialdir && *parms->initialdir) { lstrcpyn_safe(buf,parms->initialdir,sizeof(buf)); } else getcwd(buf,sizeof(buf)); SetWindowText(edit,filepart); SendMessage(hwnd, WM_USER+100, 0x103, (LPARAM)buf); } SetWindowPos(hwnd,NULL,0,0,600, 400, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE); SendMessage(hwnd,WM_USER+100,1,0); // refresh list } break; case WM_USER+100: switch (wParam) { case 0x103: // update directory combo box -- destroys buffer pointed to by lParam if (lParam) { char *path = (char*)lParam; HWND combo=GetDlgItem(hwnd,0x103); SendMessage(combo,CB_RESETCONTENT,0,0); WDL_remove_trailing_dirchars(path); while (path[0]) { SendMessage(combo,CB_ADDSTRING,0,(LPARAM)path); WDL_remove_filepart(path); WDL_remove_trailing_dirchars(path); } SendMessage(combo,CB_ADDSTRING,0,(LPARAM)"/"); SendMessage(combo,CB_SETCURSEL,0,0); } break; case 1: { BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA); if (parms) { char buf[maxPathLen]; const char *filt = NULL; buf[0]=0; int a = (int) SendDlgItemMessage(hwnd,0x105,CB_GETCURSEL,0,0); if (a>=0) filt = (const char *)SendDlgItemMessage(hwnd,0x105,CB_GETITEMDATA,a,0); a = (int) SendDlgItemMessage(hwnd,0x103,CB_GETCURSEL,0,0); if (a>=0) SendDlgItemMessage(hwnd,0x103,CB_GETLBTEXT,a,(LPARAM)buf); if (buf[0]) parms->scan_path(buf, filt, parms->mode == BrowseFile_State::OPENDIR); else parms->viewlist.DeleteAll(); HWND list = GetDlgItem(hwnd,0x104); ListView_SetItemCount(list, 0); // clear selection ListView_SetItemCount(list, parms->viewlist.GetSize()); ListView_RedrawItems(list,0, parms->viewlist.GetSize()); } } break; } break; case WM_GETMINMAXINFO: { LPMINMAXINFO p=(LPMINMAXINFO)lParam; p->ptMinTrackSize.x = 300; p->ptMinTrackSize.y = 300; } break; case WM_SIZE: { BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA); // reposition controls RECT r; GetClientRect(hwnd,&r); const int buth = 24, cancelbutw = 50, okbutw = parms->mode == BrowseFile_State::OPENDIR ? 120 : 50; const int xborder = 4, yborder=8; const int fnh = 20, fnlblw = parms->mode == BrowseFile_State::OPENDIR ? 70 : 50; int ypos = r.bottom - 4 - buth; int xpos = r.right; SetWindowPos(GetDlgItem(hwnd,IDCANCEL), NULL, xpos -= cancelbutw + xborder, ypos, cancelbutw,buth, SWP_NOZORDER|SWP_NOACTIVATE); SetWindowPos(GetDlgItem(hwnd,IDOK), NULL, xpos -= okbutw + xborder, ypos, okbutw,buth, SWP_NOZORDER|SWP_NOACTIVATE); HWND emb = GetDlgItem(hwnd,0x102); if (emb) { RECT sr; GetClientRect(emb,&sr); if (ypos > r.bottom-4-sr.bottom) ypos = r.bottom-4-sr.bottom; SetWindowPos(emb,NULL, xborder,ypos, xpos - xborder*2, sr.bottom, SWP_NOZORDER|SWP_NOACTIVATE); ShowWindow(emb,SW_SHOWNA); } HWND filt = GetDlgItem(hwnd,0x105); if (filt) { SetWindowPos(filt, NULL, xborder*2 + fnlblw, ypos -= fnh + yborder, r.right-fnlblw-xborder*3, fnh, SWP_NOZORDER|SWP_NOACTIVATE); } SetWindowPos(GetDlgItem(hwnd,0x100), NULL, xborder*2 + fnlblw, ypos -= fnh + yborder, r.right-fnlblw-xborder*3, fnh, SWP_NOZORDER|SWP_NOACTIVATE); SetWindowPos(GetDlgItem(hwnd,0x101), NULL, xborder, ypos, fnlblw, fnh, SWP_NOZORDER|SWP_NOACTIVATE); SetWindowPos(GetDlgItem(hwnd,0x103), NULL, xborder, 0, r.right-xborder*2, fnh, SWP_NOZORDER|SWP_NOACTIVATE); SetWindowPos(GetDlgItem(hwnd,0x104), NULL, xborder, fnh+yborder, r.right-xborder*2, ypos - (fnh+yborder) - yborder, SWP_NOZORDER|SWP_NOACTIVATE); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case 0x105: if (HIWORD(wParam) == CBN_SELCHANGE) { SendMessage(hwnd,WM_USER+100,1,0); // refresh list } return 0; case 0x103: if (HIWORD(wParam) == CBN_SELCHANGE) { SendMessage(hwnd,WM_USER+100,1,0); // refresh list } return 0; case IDCANCEL: EndDialog(hwnd,0); return 0; case IDOK: { char buf[maxPathLen], msg[2048]; buf[0]=0; int a = (int) SendDlgItemMessage(hwnd,0x103,CB_GETCURSEL,0,0); if (a>=0) { SendDlgItemMessage(hwnd,0x103,CB_GETLBTEXT,a,(LPARAM)buf); size_t buflen = strlen(buf); if (!buflen) strcpy(buf,"/"); else { if (buflen > sizeof(buf)-2) buflen = sizeof(buf)-2; if (buf[buflen-1]!='/') { buf[buflen++] = '/'; buf[buflen]=0; } } } GetDlgItemText(hwnd,0x100,msg,sizeof(msg)); BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA); int cnt; if (parms->mode == BrowseFile_State::OPENMULTI && (cnt=ListView_GetSelectedCount(GetDlgItem(hwnd,0x104)))>1 && (!*msg || !strcmp(msg,multiple_files))) { HWND list = GetDlgItem(hwnd,0x104); WDL_TypedBuf<char> fs; fs.Set(buf,strlen(buf)+1); int a = ListView_GetNextItem(list,-1,LVNI_SELECTED); while (a != -1 && fs.GetSize() < 4096*4096 && cnt--) { const char *fn = NULL; struct BrowseFile_State::rec *rec = parms->viewlist.EnumeratePtr(a,&fn); if (!rec) break; if (*fn) fn++; // skip type ident fs.Add(fn,strlen(fn)+1); a = ListView_GetNextItem(list,a,LVNI_SELECTED); } fs.Add("",1); parms->fnout = (char*)malloc(fs.GetSize()); if (parms->fnout) memcpy(parms->fnout,fs.Get(),fs.GetSize()); EndDialog(hwnd,1); return 0; } else { if (msg[0] == '.' && (msg[1] == '.' || msg[1] == 0)) { if (msg[1] == '.') SendDlgItemMessage(hwnd,0x103,CB_SETCURSEL,a+1,0); SetDlgItemText(hwnd,0x100,""); SendMessage(hwnd,WM_USER+100,1,0); // refresh list return 0; } else if (msg[0] == '/') lstrcpyn_safe(buf,msg,sizeof(buf)); else lstrcatn(buf,msg,sizeof(buf)); } switch (parms->mode) { case BrowseFile_State::OPENDIR: if (!buf[0]) return 0; else if (msg[0]) { // navigate to directory if filepart set DIR *dir = opendir(buf); if (!dir) { snprintf(msg,sizeof(msg),"Error opening directory:\r\n\r\n%s\r\n\r\nCreate?",buf); if (MessageBox(hwnd,msg,"Create directory?",MB_OKCANCEL)==IDCANCEL) return 0; CreateDirectory(buf,NULL); dir=opendir(buf); } if (!dir) { MessageBox(hwnd,"Error creating directory","Error",MB_OK); return 0; } closedir(dir); SendMessage(hwnd, WM_USER+100, 0x103, (LPARAM)buf); SetDlgItemText(hwnd,0x100,""); SendMessage(hwnd,WM_USER+100,1,0); // refresh list return 0; } else { DIR *dir = opendir(buf); if (!dir) return 0; closedir(dir); } break; case BrowseFile_State::SAVE: if (!buf[0]) return 0; else { struct stat st={0,}; DIR *dir = opendir(buf); if (dir) { closedir(dir); SendMessage(hwnd, WM_USER+100, 0x103, (LPARAM)buf); SetDlgItemText(hwnd,0x100,""); SendMessage(hwnd,WM_USER+100,1,0); // refresh list return 0; } if (!stat(buf,&st)) { snprintf(msg,sizeof(msg),"File exists:\r\n\r\n%s\r\n\r\nOverwrite?",buf); if (MessageBox(hwnd,msg,"Overwrite file?",MB_OKCANCEL)==IDCANCEL) return 0; } } break; default: if (!buf[0]) return 0; else { struct stat st={0,}; DIR *dir = opendir(buf); if (dir) { closedir(dir); SendMessage(hwnd, WM_USER+100, 0x103, (LPARAM)buf); SetDlgItemText(hwnd,0x100,""); SendMessage(hwnd,WM_USER+100,1,0); // refresh list return 0; } if (stat(buf,&st)) { snprintf(msg,sizeof(msg),"File does not exist:\r\n\r\n%s",buf); MessageBox(hwnd,msg,"File not found",MB_OK); return 0; } } break; } if (parms->fnout) { lstrcpyn_safe(parms->fnout,buf,parms->fnout_sz); } else { size_t l = strlen(buf); parms->fnout = (char*)calloc(l+2,1); memcpy(parms->fnout,buf,l); } } EndDialog(hwnd,1); return 0; } break; case WM_NOTIFY: { LPNMHDR l=(LPNMHDR)lParam; if (l->code == LVN_GETDISPINFO) { BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA); NMLVDISPINFO *lpdi = (NMLVDISPINFO*) lParam; const int idx=lpdi->item.iItem; if (l->idFrom == 0x104 && parms && idx >=0 && idx < parms->viewlist.GetSize()) { const char *fn = NULL; struct BrowseFile_State::rec *rec = parms->viewlist.EnumeratePtr(idx,&fn); if (rec && fn) { if (lpdi->item.mask&LVIF_TEXT) { switch (lpdi->item.iSubItem) { case 0: if (fn[0]) lstrcpyn_safe(lpdi->item.pszText,fn+1,lpdi->item.cchTextMax); break; case 1: if (fn[0] == 1) { lstrcpyn_safe(lpdi->item.pszText,"<DIR>",lpdi->item.cchTextMax); } else { static const char *tab[]={ "bytes","KB","MB","GB" }; int lf=0; WDL_INT64 s=rec->size; if (s<1024) { snprintf(lpdi->item.pszText,lpdi->item.cchTextMax,"%d %s ",(int)s,tab[0]); break; } int w = 1; do { w++; lf = (int)(s&1023); s/=1024; } while (s >= 1024 && w<4); snprintf(lpdi->item.pszText,lpdi->item.cchTextMax,"%d.%d %s ",(int)s,(int)((lf*10.0)/1024.0+0.5),tab[w-1]); } break; case 2: if (rec->date > 0 && rec->date < WDL_INT64_CONST(0x793406fff)) { struct tm *a=localtime(&rec->date); if (a) { char str[512]; strftime(str,sizeof(str),"%c",a); lstrcpyn(lpdi->item.pszText, str,lpdi->item.cchTextMax); } } break; } } } } } else if (l->code == LVN_ODFINDITEM) { } else if (l->code == LVN_ITEMCHANGED) { const int selidx = ListView_GetNextItem(l->hwndFrom, -1, LVNI_SELECTED); if (selidx>=0) { BrowseFile_State *parms = (BrowseFile_State *)GetWindowLongPtr(hwnd,GWLP_USERDATA); if (parms && parms->mode == BrowseFile_State::OPENMULTI && ListView_GetSelectedCount(l->hwndFrom)>1) { SetDlgItemText(hwnd,0x100,multiple_files); } else { const char *fn = NULL; struct BrowseFile_State::rec *rec = parms ? parms->viewlist.EnumeratePtr(selidx,&fn) : NULL; if (rec) { if (fn && fn[0]) SetDlgItemText(hwnd,0x100,fn+1); } } } } else if (l->code == NM_DBLCLK) { SendMessage(hwnd,WM_COMMAND,IDOK,0); } } break; } return 0; }