|
|
1.1 root 1: /************************************************************************
2:
3: File: open.c
4:
5: Purpose:
6:
7: This file contains the routines to control the CDTEST.EXE "Open" dialog
8: box. The "Open" dialog box allows the user to enter values into an
9: OPENFILENAME structure and then create GetOpenFileName() dialog boxes
10: on the fly.
11:
12: Functions:
13:
14: DoOpenDialog() -- starts off the main dialog for "open"
15:
16: OpenFunc() -- Callback function for main dialog
17:
18: InitOpenStruct() -- Fills initial OPENFILENAME structure.
19:
20: FillOpenDlg() -- Fills the dialog with the values from
21: the OPENFILENAME structure.
22:
23: GetOpenDlg() -- Retrieves the users entries from the
24: main dialog and puts them in the
25: OPENFILENAME structure.
26:
27: InitFilterString() -- Creates filter string
28:
29: InitCustFiltString() -- Creates custom filter string
30:
31: InterpretCustomFilterString() -- Parses custom filter string returned
32: from GetOpenFileName()
33:
34: GetCorrectResourceHandle() -- Loads custom templates from file
35: as resource handles
36:
37: OpenSaveHookProc() -- The hook function that will be
38: called if GetOpen/Save is called
39: with the OFN_ENABLEHOOK flag set.
40:
41: MultiThreadOpenSave() -- Creates two Open/Save dialogs that
42: the user can simultaneously access
43:
44: OpenSaveThread1Proc() -- The starting address of thread 1
45:
46: OpenSaveThread2Proc() -- The starting address of thread 2
47:
48: DoOpenSaveStuff() -- Does the actuall calling of
49: GetOpen/SaveFileName()
50:
51: OpenMultiThreadEnableButtons() -- Enables and disables buttons in
52: main dialog. Needed when multi-
53: threading.
54:
55: ************************************************************************/
56:
57: #include <windows.h>
58: #include <commdlg.h>
59: #include <stdlib.h>
60: #include <winnls.h>
61: #include "cdtest.h"
62: #include "open.h"
63: #include "save.h"
64: #include "dlgs.h" //include file that contains all #defines for the
65: //commdlg dialog templates.
66:
67:
68: /* All functions defined in this file + 1 external function
69: and one external variable */
70:
71: extern UINT uMode ; //see cdtest.c
72: extern LONG MyAtol(LPTSTR, BOOL, LPBOOL) ;
73: void InterpretCustomFilterString(void) ;
74: HANDLE GetCorrectResourceHandle(void) ;
75: void DoOpenSaveStuff(LPOPENFILENAME) ;
76: UINT APIENTRY OpenSaveHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam) ;
77: DWORD OpenSaveThread1Proc(LPDWORD) ;
78: DWORD OpenSaveThread2Proc(LPDWORD) ;
79: void MultiThreadOpenSave(void) ;
80: void OpenMultiThreadEnableButtons(BOOL, HWND) ;
81:
82:
83: /* All global variables defined in this file */
84:
85: HWND hwndMainDialog ; //global handle for open dialog.
86:
87: HANDLE hRes ; //handles to the resource and dialog for
88: HANDLE hDialog ; //ofn_enabletemplatehandle
89:
90: HBRUSH hBrushDlg ;
91: HBRUSH hBrushEdit ; //brush handles for new colors done with hook proc
92: HBRUSH hBrushButton ;
93:
94: HANDLE hOpenSaveThread1, hOpenSaveThread2 ; //variables for the
95: DWORD dwThreadID1, dwThreadID2 ; //multithreading part
96: DWORD dwThreadParm1, dwThreadParm2 ;
97: OPENFILENAME ofnThread1, ofnThread2 ;
98: int nOpenDialogCount ;
99:
100:
101:
102:
103:
104: /************************************************************************
105:
106: Function: DoOpenDialog(HWND)
107:
108: Purpose: To create the GetOpenFileName() and GetSaveFileName()
109: creation dialog.
110:
111: Returns: Nothing.
112:
113: Comments:
114:
115: GetOpenFileName() and GetSaveFileName() are similiar enough so that
116: the same dialog can be used to edit their creation structure elements,
117: so a global variable "bDoOpenDlg" keeps track of which one to create
118: when the user clicks the OK or Multithread buttons...
119:
120: ************************************************************************/
121:
122:
123: void DoOpenDialog(HWND hwnd)
124: {
125:
126: bDoOpenDlg = TRUE ;
127:
128:
129: DialogBox(hInst, MAKEINTRESOURCE(ID_OPENDIALOG), hwnd, OpenFunc) ;
130:
131: }
132:
133:
134:
135:
136:
137:
138: /************************************************************************
139:
140:
141: Function: OpenFunc(HWND, UINT, UINT, LONG)
142:
143: Purpose:
144:
145: This is the callback function for the dialog box containing the
146: GetOpenFileName() and the GetSaveFileName() creation options.
147:
148: This function will handle the messages for this dialog and create
149: either a GetOpenFileName() dialog or a GetSaveFileName() dialog
150: depending on the state of the bDoOpenDlg variable.
151:
152: Returns: TRUE or FALSE depending on the situation.
153:
154: Comments:
155:
156:
157: ************************************************************************/
158:
159:
160: BOOL APIENTRY OpenFunc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
161: {
162: switch (msg)
163: {
164:
165: case WM_INITDIALOG:
166:
167: if (bDoOpenDlg)
168: SetWindowText(hwnd, TEXT("GetOpenFileName()")) ;
169: else
170: SetWindowText(hwnd, TEXT("GetSaveFileName()")) ;
171:
172:
173: /* initialize the OPENFILENAME structure members */
174:
175: InitOpenStruct(hwnd, &ofn) ;
176:
177:
178: /* Fill these values into the creation dialog */
179:
180: FillOpenDlg(hwnd, &ofn) ;
181:
182:
183: /* There are three separate OPENFILENAME structures. One for
184: the main Open/Save dialog and one for each multithreaded dialog.
185: Set them equal to begin with */
186:
187: *(&ofnThread1) = *(&ofnThread2) = *(&ofn) ;
188:
189: hwndMainDialog = hwnd ;
190:
191: SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEO)) ;
192:
193: break ;
194:
195:
196:
197: case UMSG_DECREMENTDLGCOUNT: //user defined message indicating
198: //the closure of a multithreaded dialog
199:
200: /* When we are multithreading, there is nothing to prevent the
201: user from interacting with the creation dialog once the first
202: GetOpen(Save) file name dialog has returned. So, in order
203: to prevent the Multithread" button from being pressed again
204: before the previous two multithreaded dialogs have been canceled,
205: disable the controls until we get a message from each thread
206: that the dialog has ended */
207:
208:
209: nOpenDialogCount-- ;
210:
211: if (nOpenDialogCount == 0)
212: OpenMultiThreadEnableButtons(TRUE, hwnd) ;
213:
214: break ;
215:
216:
217: case WM_COMMAND:
218: {
219: switch (LOWORD(wParam))
220: {
221:
222: case IDOK:
223: GetOpenDlg(hwnd, &ofn) ; //get the user's input
224: DoOpenSaveStuff(&ofn) ; //do the dialog
225: break ;
226:
227:
228: case IDCANCEL:
229: EndDialog(hwnd, FALSE) ;
230: break ;
231:
232:
233: case ID_RESETOPEN:
234:
235: SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
236: (WPARAM) 0, (LPARAM) 0) ;
237:
238: InitOpenStruct(hwnd, &ofn) ;
239:
240: FillOpenDlg(hwnd, &ofn) ;
241:
242: SendDlgItemMessage(hwnd, ID_NULLSTRUCTO, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
243: SendDlgItemMessage(hwnd, ID_USEHINSTO, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
244:
245: *(&ofnThread1) = *(&ofnThread2) = *(&ofn) ;
246:
247: SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEO)) ;
248:
249: break ;
250:
251:
252: case ID_ADD1O:
253:
254: GetDlgItemText(hwnd, ID_FILTERO, szTemp, 100) ;
255:
256: if (*szTemp)
257: {
258: SendDlgItemMessage(hwnd, ID_FILTERO, CB_ADDSTRING, (WPARAM) 0,
259: (LPARAM) (LPTSTR) szTemp) ;
260: SetWindowText(GetDlgItem(hwnd, ID_FILTERO), TEXT("")) ;
261: }
262: break ;
263:
264:
265: case ID_ADD2O:
266:
267: GetDlgItemText(hwnd, ID_CUSTFILTO, szTemp, 100) ;
268:
269: if (*szTemp)
270: {
271: SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_ADDSTRING, (WPARAM) 0,
272: (LPARAM) (LPTSTR) szTemp) ;
273: SetWindowText(GetDlgItem(hwnd, ID_CUSTFILTO), TEXT("")) ;
274: }
275: break ;
276:
277:
278: case ID_CLEAR1O:
279: SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
280: (WPARAM) 0, (LPARAM) 0) ;
281: break ;
282:
283: case ID_CLEAR2O:
284: SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_RESETCONTENT,
285: (WPARAM) 0, (LPARAM) 0) ;
286: break ;
287:
288: case ID_MULTIOPEN:
289:
290: /* First, disable the OK, Cancel, and MultiThread buttons */
291:
292: OpenMultiThreadEnableButtons(FALSE, hwnd) ;
293:
294:
295: /* Then multithread the dialogs */
296:
297: nOpenDialogCount = 2 ;
298:
299: MultiThreadOpenSave() ;
300:
301: break ;
302:
303:
304: default: //end WM_COMMAND case
305: break ;
306: }
307: }
308:
309: default:
310:
311: /* If the help button is pressed in the GetOpen/SaveFileName()
312: dialogs, it will send a message Registered with RegisterWindowMessage()
313: to the parent window. The message nHelpMessage was registered
314: at application startup */
315:
316: if (msg == nHelpMessage)
317: MessageBox(GetForegroundWindow(),
318: TEXT("Hello from the help button"),
319: TEXT("Open Help Button"), MB_OK | MB_APPLMODAL) ;
320:
321: break ;
322:
323: }
324:
325: return FALSE ;
326: }
327:
328:
329:
330:
331:
332:
333:
334: /************************************************************************
335:
336:
337: Function: InitOpenStruct(HWND, LPOPENFILENAME)
338:
339: Purpose:
340:
341: Initializes the OPENFILENAME structure. The structure is referenced
342: via a pointer passed in as the second parameter so that we can pass
343: any of the three OPENFILENAME structures into this function and
344: Initialize them.
345:
346: Returns: Nothing.
347:
348: Comments:
349:
350: The szFilterInits and szCustFiltInits arrays are initialized to
351: contain some default strings. Eventually the strings in
352: these arrays must be arranged one after the other with a null
353: character between them and two null characters at the end:
354:
355: "Text files\0*.txt\0All files\0*.*\0\0"
356:
357: ************************************************************************/
358:
359:
360: void InitOpenStruct(HWND hwnd, LPOPENFILENAME po)
361: {
362: int i = 0 ;
363: szFileName[0] = 0 ;
364: szFileTitle[0] = 0 ;
365:
366: dwFlags = OFN_READONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_SHOWHELP ;
367:
368: if (bDoOpenDlg)
369: lstrcpy(szDlgTitle, TEXT("Open Dialog Title")) ;
370: else
371: lstrcpy(szDlgTitle, TEXT("Save Dialog Title")) ;
372:
373: lstrcpy(szDefExt, TEXT("rat")) ;
374: lstrcpy(szInitialDir, TEXT("c:\\")) ;
375: lstrcpy(szTempName, TEXT("opentemp1")) ;
376:
377: lstrcpy(&szFilterInits[0][0], TEXT("All Files (*.*)")) ;
378: lstrcpy(&szFilterInits[1][0], TEXT("*.*")) ;
379: lstrcpy(&szFilterInits[2][0], TEXT("Fat Files (*.fat)")) ;
380: lstrcpy(&szFilterInits[3][0], TEXT("*.fat")) ;
381: szFilterInits[4][0] = (TCHAR) 0 ;
382:
383: lstrcpy(&szCustFiltInits[0][0], TEXT("Last Filter Used")) ;
384: lstrcpy(&szCustFiltInits[1][0], TEXT("*.lst")) ;
385: szCustFiltInits[2][0] = (TCHAR) 0 ;
386:
387:
388: /*
389:
390: These two functions will create "strings" in the applications
391: data area that are in the form
392:
393: "Filter Description"\0
394: "Filter"\0
395: "Filter Description"\0
396: "Filter"\0
397: ..
398: ..
399: \0\0
400:
401: The filters must be in this form in order that the common dialogs
402: interpret it correctly...
403: */
404:
405: InitFilterString() ;
406:
407: InitCustFilterString() ;
408:
409: po->lStructSize = sizeof(OPENFILENAME) ;
410: po->hwndOwner = hwnd ;
411: po->hInstance = hInst ;
412: (LPTSTR) po->lpstrFilter = lpszFilterString ;
413: po->lpstrCustomFilter = lpszCustFilterString ;
414: po->nMaxCustFilter = MAXCUSTFILTER ;
415: po->nFilterIndex = 1L ;
416: po->lpstrFile = szFileName ;
417: po->nMaxFile = FILENAMESIZE ;
418: po->lpstrFileTitle = szFileTitle ;
419: po->nMaxFileTitle = FILETITLESIZE ;
420: po->lpstrInitialDir = szInitialDir ;
421: (LPTSTR) po->lpstrTitle = szDlgTitle ;
422: po->Flags = dwFlags ;
423: po->nFileOffset = 0 ;
424: po->nFileExtension = 0 ;
425: (LPTSTR) po->lpstrDefExt = szDefExt;
426: po->lCustData = 0L ;
427: po->lpfnHook = OpenSaveHookProc ;
428: (LPTSTR) po->lpTemplateName = szTempName ;
429:
430: return ;
431: }
432:
433:
434:
435:
436:
437:
438:
439: /************************************************************************
440:
441:
442: Function: FillOpenDlg(HWND, LPOPENFILENAME)
443:
444: Purpose:
445:
446: - This function will fill in the edit boxes that correspond to each
447: of the fields in the OPENFILENAME structure. The user can accept
448: these values to create the common dialog or edit them.
449:
450: Returns: Nothing.
451:
452: Comments:
453:
454: The contents of the strings "szShortFilter" and "szLongFilter"
455: determine how a WORD or a DWORD value is represented in the edit boxes
456:
457: ************************************************************************/
458:
459: void FillOpenDlg(HWND hwnd, LPOPENFILENAME po)
460: {
461: int i = 0 ;
462:
463: wsprintf(szTemp, szShortFilter, (int) po->lStructSize) ;
464: SetDlgItemText(hwnd, ID_STRUCTSIZEO, szTemp) ;
465:
466: wsprintf(szTemp, szLongFilter, (LONG) po->hwndOwner) ;
467: SetDlgItemText(hwnd, ID_HWNDOWNERO, szTemp) ;
468:
469: wsprintf(szTemp, szLongFilter, (LONG) po->hInstance) ;
470: SetDlgItemText(hwnd, ID_HINSTANCEO, szTemp) ;
471:
472:
473: SendDlgItemMessage(hwnd, ID_FILTERO, CB_RESETCONTENT,
474: (WPARAM) 0, (LPARAM) 0) ;
475:
476: while (szFilterInits[i][0] != (TCHAR) 0)
477: {
478: SendDlgItemMessage(hwnd, ID_FILTERO, CB_ADDSTRING, (WPARAM) 0,
479: (LPARAM) (LPTSTR) &szFilterInits[i][0]) ;
480: i++ ;
481: }
482:
483: SendDlgItemMessage(hwnd, ID_FILTERO, CB_SETCURSEL,
484: (WPARAM) 0, (LPARAM) 0 ) ;
485:
486:
487:
488: SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_RESETCONTENT,
489: (WPARAM) 0, (LPARAM) 0) ;
490:
491: for (i=0; i<2; i++)
492: SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_ADDSTRING, (WPARAM) 0,
493: (LPARAM) (LPTSTR) &szCustFiltInits[i][0]) ;
494:
495: SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_SETCURSEL,
496: (WPARAM) 0, (LPARAM) 0) ;
497:
498:
499: wsprintf(szTemp, szShortFilter, (int) po->nMaxCustFilter) ;
500: SetDlgItemText(hwnd, ID_MAXCUSTFILTO, szTemp) ;
501:
502: wsprintf(szTemp, szShortFilter, (int) po->nFilterIndex) ;
503: SetDlgItemText(hwnd, ID_FILTINDEXO, szTemp) ;
504:
505: SetDlgItemText(hwnd, ID_SZFILEO, po->lpstrFile) ;
506:
507: wsprintf(szTemp, szShortFilter, (int) po->nMaxFile) ;
508: SetDlgItemText(hwnd, ID_MAXSZFILEO, szTemp) ;
509:
510: SetDlgItemText(hwnd, ID_SZFILETITLEO, po->lpstrFileTitle) ;
511:
512: wsprintf(szTemp, szShortFilter, (int) po->nMaxFileTitle) ;
513: SetDlgItemText(hwnd, ID_MAXSZFILETITLEO, szTemp) ;
514:
515: SetDlgItemText(hwnd, ID_SZINITDIRO, po->lpstrInitialDir) ;
516:
517: SetDlgItemText(hwnd, ID_SZTITLEO, po->lpstrTitle) ;
518:
519: wsprintf(szTemp, szLongFilter, po->Flags) ;
520: SetDlgItemText(hwnd, ID_FLAGSO, szTemp) ;
521:
522: wsprintf(szTemp, szShortFilter, po->nFileOffset) ;
523: SetDlgItemText(hwnd, ID_FILEOFFO, szTemp) ;
524:
525: wsprintf(szTemp, szShortFilter, po->nFileExtension) ;
526: SetDlgItemText(hwnd, ID_FILEEXTO, szTemp) ;
527:
528: SetDlgItemText(hwnd, ID_SZDEFEXTO, po->lpstrDefExt) ;
529:
530: wsprintf(szTemp, szLongFilter, po->lCustData) ;
531: SetDlgItemText(hwnd, ID_CUSTDATAO, szTemp) ;
532:
533: wsprintf(szTemp, szLongFilter, po->lpfnHook) ;
534: SetDlgItemText(hwnd, ID_HOOKO, szTemp) ;
535:
536: SetDlgItemText(hwnd, ID_TEMPLATEO, po->lpTemplateName) ;
537:
538: return ;
539: }
540:
541:
542:
543:
544:
545:
546:
547:
548: /************************************************************************
549:
550:
551: Function: GetOpenDlg(HWND, LPOPENFILENAME)
552:
553:
554: Purpose:
555:
556: This function will retrieve the contents of each edit box corresponding
557: with each field in the OPENFILENAME structure, and fill in the
558: OPENFILENAME structure with these values.
559:
560: Returns: Nothing.
561:
562: Comments:
563:
564: if (uMode == IDM_HEXMODE), then the numbers should be interpreted as
565: hexidecimal and the MyAtol() function is called with its "bHex"
566: parameter set to true.
567:
568: ************************************************************************/
569:
570: void GetOpenDlg(HWND hwnd, LPOPENFILENAME po)
571: {
572: int i ;
573: BOOL b ;
574: TCHAR szNum[20] ;
575:
576: GetDlgItemText(hwnd, ID_STRUCTSIZEO, szNum, 20) ;
577: po->lStructSize = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
578:
579: GetDlgItemText(hwnd, ID_HWNDOWNERO, szNum, 20) ;
580: po->hwndOwner = (HWND) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
581:
582: GetDlgItemText(hwnd, ID_HINSTANCEO, szNum, 20) ;
583: po->hInstance = (HANDLE) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
584:
585:
586: /* these are just strings, no conversion necessary */
587:
588: i = 0 ;
589: while (SendDlgItemMessage(hwnd, ID_FILTERO, CB_GETLBTEXT, (WPARAM) i,
590: (LPARAM) (LPTSTR) szFilterInits[i]) != CB_ERR)
591: { i++ ; }
592:
593:
594: /* create the filter string */
595:
596: InitFilterString() ;
597:
598:
599: i = 0 ;
600:
601: while (SendDlgItemMessage(hwnd, ID_CUSTFILTO, CB_GETLBTEXT, (WPARAM) i,
602: (LPARAM) (LPTSTR) szCustFiltInits[i]) != CB_ERR)
603: { i++ ; }
604:
605:
606: InitCustFilterString() ;
607:
608:
609: GetDlgItemText(hwnd, ID_MAXCUSTFILTO, szNum, 20) ;
610: po->nMaxCustFilter = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
611:
612: GetDlgItemText(hwnd, ID_FILTINDEXO, szNum, 20) ;
613: po->nFilterIndex = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
614:
615: GetDlgItemText(hwnd, ID_SZFILEO, po->lpstrFile, MAXBUF) ;
616:
617: GetDlgItemText(hwnd, ID_MAXSZFILEO, szNum, 20) ;
618: po->nMaxFile = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
619:
620: GetDlgItemText(hwnd, ID_SZFILETITLEO, po->lpstrFileTitle, MAXBUF) ;
621:
622: GetDlgItemText(hwnd, ID_MAXSZFILETITLEO, szNum, MAXBUF) ;
623: po->nMaxFileTitle = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
624:
625: GetDlgItemText(hwnd, ID_SZINITDIRO, (LPTSTR) po->lpstrInitialDir, MAXBUF) ;
626:
627: GetDlgItemText(hwnd, ID_SZTITLEO, (LPTSTR) po->lpstrTitle, MAXBUF) ;
628:
629: GetDlgItemText(hwnd, ID_FLAGSO, szNum, 20) ;
630: po->Flags = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
631:
632: GetDlgItemText(hwnd, ID_FILEOFFO, szNum, 20) ;
633: po->nFileOffset = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
634:
635: GetDlgItemText(hwnd, ID_FILEEXTO, szNum, 20) ;
636: po->nFileExtension = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
637:
638: GetDlgItemText(hwnd, ID_SZDEFEXTO, (LPTSTR) po->lpstrDefExt, DEFEXTSIZE) ;
639:
640: GetDlgItemText(hwnd, ID_CUSTDATAO, szNum, 20) ;
641: po->lCustData = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
642:
643: GetDlgItemText(hwnd, ID_HOOKO, szNum, 20) ;
644: po->lpfnHook = (LPOFNHOOKPROC) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;
645:
646: GetDlgItemText(hwnd, ID_TEMPLATEO, (LPTSTR) po->lpTemplateName, TEMPNAMESIZE) ;
647:
648:
649: /* if we are supposed to use a preloaded resource handle, load it and put it in
650: OPENFILENAME.hInstance... */
651:
652: if (IsDlgButtonChecked(hwnd, ID_USEHINSTO) == 1)
653: po->hInstance = GetCorrectResourceHandle() ;
654:
655: return ;
656: }
657:
658:
659:
660:
661:
662:
663:
664: /************************************************************************
665:
666:
667: Function: InitFilterString(void)
668:
669:
670: Purpose:
671:
672: This function will create a "string" in memory in the form that the
673: GetOpenFileName() function will expect for the filters it fills into
674: the "List Files of Type" combo box.
675:
676: Returns: Nothing.
677:
678: Comments:
679:
680: The szFilterInits and szCustFiltInits arrays are initialized to
681: contain some default strings. Eventually the strings in
682: these arrays must be arranged one after the other with a null
683: character between them and two null characters at the end:
684:
685: "Text files\0*.txt\0All files\0*.*\0\0"
686:
687: ************************************************************************/
688:
689:
690: void InitFilterString(void)
691: {
692: int i ;
693: int nInc = 0 ;
694: LPTSTR lpStr = szFilterString ;
695:
696:
697: /* First, zero out this memory just for the sake of sanity */
698:
699: for (i=0; i<MAXBUF; i++)
700: szFilterString[i] = 0 ;
701:
702:
703: /* Now, for each string in the szFilterInits array, concatenate it to
704: the last one right after the last one's null terminator */
705:
706: i = 0 ;
707:
708: while (szFilterInits[i][0] != (TCHAR) 0)
709: {
710: lstrcpy(lpStr, &szFilterInits[i][0]) ;
711: nInc+=lstrlen(&szFilterInits[i][0]) + 1 ; //1 past null term...
712: lpStr = &szFilterString[nInc] ;
713: i++ ;
714: }
715:
716: szFilterString[nInc] = (TCHAR) 0 ; //double terminator
717:
718:
719: /* Set the lpszFilterString to point to the memory we just filled in
720: with the filters because lpszFilterString is what is in
721: OPENFILENAME->lpstrFilter */
722:
723: lpszFilterString = szFilterString ;
724:
725: return ;
726: }
727:
728:
729:
730:
731:
732:
733:
734:
735:
736: /************************************************************************
737:
738:
739: Function: InitCustFiltString(void)
740:
741:
742: Purpose:
743:
744: This function will create a "string" in memory in the form that the
745: GetOpenFileName() function will expect for a custom filter.
746:
747: Returns: Nothing.
748:
749: Comments:
750:
751: The szFilterInits and szCustFiltInits arrays are initialized to
752: contain some default strings. Eventually the strings in
753: these arrays must be arranged one after the other with a null
754: character between them and two null characters at the end:
755:
756: "Text files\0*.txt\0All files\0*.*\0\0"
757:
758: This program initializes these strings, but they do not need to be
759: initialized. The GetOpenFileName() functiion will write a filter
760: into this memory area if the user types a new filter into the
761: "FileName" box and returns by clicking the OK button (indicating that
762: a file matching that filter was found).
763:
764: ************************************************************************/
765:
766:
767: void InitCustFilterString(void)
768: {
769: int i ;
770: LPTSTR lpStr = szCustFilterString ;
771: int nInc = 0 ;
772:
773: for (i=0; i<MAXBUF; i++)
774: szCustFilterString[i] = 0 ;
775:
776: i = 0 ;
777:
778: for(i=0; i<2; i++) //only two for the custom filter
779: {
780: lstrcpy(lpStr, &szCustFiltInits[i][0]) ;
781: nInc+=lstrlen(&szCustFiltInits[i][0]) + 1 ;
782: lpStr = &szCustFilterString[nInc] ;
783: }
784:
785: szCustFilterString[nInc] = (TCHAR) 0 ;
786:
787: lpszCustFilterString = szCustFilterString ;
788:
789: return ;
790: }
791:
792:
793:
794:
795:
796:
797:
798:
799:
800: /************************************************************************
801:
802: Function: InterpretCustomFilterString(void)
803:
804:
805: Purpose:
806:
807: This function will parse the memory that is being used for the
808: custom filter string. If the user returned TRUE after entering
809: their own filter, the new filter will be here and so we need to
810: add it to our custom filter init array...
811:
812: Returns: Nothing.
813:
814: Comments:
815:
816: ************************************************************************/
817:
818: void InterpretCustomFilterString(void)
819: {
820: LPTSTR pNext ;
821:
822: int nCount = lstrlen(ofn.lpstrCustomFilter) ;
823:
824: pNext = ofn.lpstrCustomFilter + nCount + 1 ; //one past the NULL
825:
826:
827: /* add it to the filter inits array */
828:
829: lstrcpy(&szCustFiltInits[0][0], ofn.lpstrCustomFilter) ;
830: lstrcpy(&szCustFiltInits[1][0], pNext) ;
831:
832: }
833:
834:
835:
836:
837:
838:
839:
840:
841:
842: /************************************************************************
843:
844: Function: GetCorrectResourceHandle(void)
845:
846: Purpose:
847:
848: This function will use FindResource() to find the correct custom
849: template resource, use LoadResource() to get a handle to it.
850:
851: Returns: A handle to a custom template resource.
852:
853: Comments:
854:
855: The names for the custom template for GetOpenFileName() are
856:
857: "opentemp1" -- normal
858: "opentemp2" -- contains a multi-select list box for the file names
859:
860: If the user has marked the "Preloaded Template" box and specified
861: OFN_ENABLETEMPLATEHANDLE in the "Flags" edit box, this handle
862: will be used to create the GetOpenFileName() dialog box.
863:
864: ************************************************************************/
865:
866:
867: HANDLE GetCorrectResourceHandle(void)
868: {
869: if (ofn.Flags & OFN_ALLOWMULTISELECT)
870: {
871: hRes = FindResource(hInst, TEXT("opentemp2"), RT_DIALOG) ;
872: hDialog = LoadResource(hInst, hRes) ;
873: }
874:
875: else
876: {
877: hRes = FindResource(hInst, TEXT("opentemp1"), RT_DIALOG) ;
878: hDialog = LoadResource(hInst, hRes) ;
879: }
880:
881: return hDialog ;
882: }
883:
884:
885:
886:
887:
888:
889:
890: /************************************************************************
891:
892: Function: OpenSaveHookProc(HWND, UINT, UINT, LONG) ;
893:
894: Purpose:
895:
896: This function is the hook function for the GetOpenFileName() function.
897: If GetOpenFileName() is called with the OFN_ENABLEHOOK flag, this
898: function will be called before the normal GetOpenFileName() dialog
899: function is called.
900:
901: Returns: FALSE to pass the message on to the normal GetOpenFileName()
902: logic, TRUE to discard the message.
903:
904: Comments:
905:
906: To enable this function in this program, enter the value for
907: OFN_ENABLEHOOK in the "Flags" edit box.
908:
909: ************************************************************************/
910:
911:
912: UINT APIENTRY OpenSaveHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
913: {
914: LPOPENFILENAME pOfn ;
915: TCHAR szMsg[50] ;
916:
917: switch(msg)
918: {
919: case WM_INITDIALOG:
920:
921: pOfn = (LPOPENFILENAME) lParam ;
922:
923:
924: /* During initialization, if there is a hook proc, the getopen()
925: code will send pointer to the OPENFILENAME strucure in the
926: lParam. To demonstrate this, pop up a message box if this
927: structure has a non zero value in the lCustData structure member */
928:
929:
930: if (pOfn->lCustData != 0L)
931: {
932: wsprintf(szMsg, TEXT("OPENFILENAME->lCustData is: %ld"), pOfn->lCustData) ;
933:
934: MessageBox(hwnd, szMsg, TEXT("lCustData Sent!"), MB_OK) ;
935: }
936:
937: SetWindowText(hwnd, TEXT("Open Hook Proc Dialog")) ;
938:
939: break ;
940:
941:
942: /* use the WM_CTLCOLOR* messages to change the color of the Open
943: dialog */
944:
945: case WM_CTLCOLORDLG:
946:
947: if (!hBrushDlg)
948: hBrushDlg = GetStockObject(LTGRAY_BRUSH) ;
949:
950: return (UINT) hBrushDlg ;
951:
952: break ;
953:
954:
955: case WM_CTLCOLORBTN:
956:
957: SetBkMode((HDC) wParam, TRANSPARENT) ; //sets background color
958: //for push and check box
959: //buttons...
960:
961: if (!hBrushButton)
962: hBrushButton = GetStockObject(LTGRAY_BRUSH) ;
963:
964: return (UINT) hBrushButton ;
965:
966: break ;
967:
968:
969: case WM_CTLCOLORSTATIC:
970:
971: SetTextColor((HDC) wParam, RGB(0x00, 0xff, 0x00)) ; //green
972: SetBkMode((HDC) wParam, TRANSPARENT) ; //transparent text
973:
974: if (!hBrushDlg)
975: hBrushDlg = GetStockObject(LTGRAY_BRUSH) ;
976:
977: return (UINT) hBrushDlg ;
978:
979: break ;
980:
981:
982: case WM_COMMAND:
983: switch (LOWORD(wParam))
984: {
985: case chx1:
986: MessageBox(hwnd, TEXT("Read-Only button clicked..."),
987: TEXT("Open"), MB_OK | MB_APPLMODAL) ;
988: break ;
989:
990: case ID_FILEPREVIEW:
991: MessageBox(hwnd, TEXT("File Preview Button Clicked"),
992: TEXT("Open"), MB_OK | MB_APPLMODAL) ;
993: break ;
994:
995: default: break ;
996: }
997: break ;
998:
999: default:
1000:
1001: if (msg == nOpenShareVMsg)
1002: {
1003: MessageBox(hwnd, TEXT("The SHAREVSTRING message is here!"),
1004: TEXT("Open"),
1005: MB_ICONEXCLAMATION | MB_OK | MB_APPLMODAL) ;
1006:
1007: return OFN_SHAREWARN ;
1008: }
1009: break ;
1010: }
1011:
1012: return FALSE ; //send msg to the common dialog code
1013: }
1014:
1015:
1016:
1017:
1018:
1019:
1020:
1021:
1022:
1023: /************************************************************************
1024:
1025: Function: MultiThreadOpenSave(void)
1026:
1027: Purpose:
1028:
1029: This function will start two threads and then return. The two
1030: threads will create GetOpenFileName() dialogs, and the user
1031: can interact with two Open dialogs at once.
1032:
1033: Returns: Nothing.
1034:
1035: Comments:
1036:
1037: This will create two Open dialogs, but they will be created in the
1038: same location on the screen. The only way to change that would be
1039: to call the function with a hookproc and move one of the windows.
1040:
1041: But that would mean that if the user did not enter OFN_ENABLEHOOK
1042: in the "Flags" edit box, we would be no better off than before. So,
1043: in order to see both dialogs, you just have to move the top one out
1044: of the way a little.
1045:
1046: Multithreading note:
1047:
1048: This function will return before the common dialog functions return.
1049: Therefore, do not pass any parameters to this function that will be
1050: referenced by the common dialogs because as soon as this function
1051: ends those parameters will be gone.
1052:
1053: ************************************************************************/
1054:
1055: void MultiThreadOpenSave(void)
1056: {
1057:
1058: if (!(hOpenSaveThread1 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
1059: (LPTHREAD_START_ROUTINE) OpenSaveThread1Proc,
1060: &dwThreadParm1, CREATE_SUSPENDED, &dwThreadID1)))
1061:
1062: {
1063: MessageBox(GetForegroundWindow(), TEXT("Cannot create thread 1"), NULL, MB_OK | MB_ICONEXCLAMATION) ;
1064: OpenMultiThreadEnableButtons(TRUE, hwndMainDialog) ;
1065: nOpenDialogCount = 0 ;
1066: return ;
1067: }
1068:
1069:
1070:
1071: if (!(hOpenSaveThread2 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
1072: (LPTHREAD_START_ROUTINE) OpenSaveThread2Proc,
1073: &dwThreadParm2, CREATE_SUSPENDED, &dwThreadID2)))
1074: {
1075: MessageBox(GetForegroundWindow(), TEXT("Cannot create thread 2"), NULL, MB_OK | MB_ICONEXCLAMATION) ;
1076: OpenMultiThreadEnableButtons(TRUE, hwndMainDialog) ;
1077: nOpenDialogCount = 0 ;
1078: return ;
1079: }
1080:
1081:
1082: ResumeThread(hOpenSaveThread1) ;
1083: ResumeThread(hOpenSaveThread2) ;
1084:
1085: }
1086:
1087:
1088:
1089:
1090:
1091:
1092:
1093: /************************************************************************
1094:
1095: Function: OpenSaveThreadProc1(LPDWORD)
1096:
1097: Purpose:
1098:
1099: This is the address where the first thread starts executing.
1100:
1101: Returns: Any DWORD value.
1102:
1103: Comments:
1104:
1105: ************************************************************************/
1106:
1107:
1108: DWORD OpenSaveThread1Proc(LPDWORD pDw)
1109: {
1110:
1111: /* Get the user's input */
1112:
1113: GetOpenDlg(hwndMainDialog, &ofnThread1) ;
1114:
1115:
1116: /* Do the dialog */
1117:
1118: DoOpenSaveStuff(&ofnThread1) ;
1119:
1120:
1121: /* send a message to the parent telling it to decrement the dialog count.
1122: When the dialog count reaches zero, all the buttons are enabled again. */
1123:
1124: SendMessage(hwndMainDialog, UMSG_DECREMENTDLGCOUNT, 0, 0L) ;
1125:
1126: return 0L ;
1127: }
1128:
1129:
1130:
1131:
1132:
1133:
1134:
1135: /************************************************************************
1136:
1137: Function: OpenSaveThreadProc2(LPDWORD)
1138:
1139: Purpose:
1140:
1141: This is the address where the second thread starts executing.
1142:
1143: Returns: Any DWORD value.
1144:
1145: Comments:
1146:
1147: ************************************************************************/
1148:
1149: DWORD OpenSaveThread2Proc(LPDWORD pDw)
1150: {
1151: GetOpenDlg(hwndMainDialog, &ofnThread2) ;
1152:
1153: DoOpenSaveStuff(&ofnThread2) ;
1154:
1155: SendMessage(hwndMainDialog, UMSG_DECREMENTDLGCOUNT, 0, 0L) ;
1156:
1157: return 0L ;
1158: }
1159:
1160:
1161:
1162:
1163:
1164:
1165:
1166: /************************************************************************
1167:
1168: Function: DoOpenSaveStuff(LPOPENFILENAME)
1169:
1170: Purpose:
1171:
1172: This is the function that actually calls GetOpenFileName() or
1173: GetSaveFileName(). It receives a pointer to the structure to
1174: use as its only parameter.
1175:
1176: Returns: Nothing.
1177:
1178: Comments:
1179:
1180: ************************************************************************/
1181:
1182: void DoOpenSaveStuff(LPOPENFILENAME po)
1183: {
1184: BOOL bRet = TRUE ;
1185:
1186:
1187: /* If bOpenDlg is TRUE, do GetOpenFileName(), else do GetSave().
1188: If the "NULL Structure" button is checked, send in a NULL pointer
1189: to the function */
1190:
1191: if (bDoOpenDlg)
1192: {
1193: if (IsDlgButtonChecked(hwndMainDialog, ID_NULLSTRUCTO) == 1)
1194: bRet = GetOpenFileName((LPOPENFILENAME) NULL) ;
1195: else
1196: bRet = GetOpenFileName(po) ;
1197: }
1198:
1199: else
1200: {
1201: if (IsDlgButtonChecked(hwndMainDialog, ID_NULLSTRUCTO))
1202: bRet = GetSaveFileName((LPOPENFILENAME) NULL) ;
1203: else
1204: bRet = GetSaveFileName(po) ;
1205: }
1206:
1207:
1208: /* Record the results */
1209:
1210: wsprintf(szTemp, szLongFilter, CommDlgExtendedError()) ;
1211: SetDlgItemText(hwndMainDialog, ID_ERRORO, szTemp) ;
1212:
1213: wsprintf(szTemp, szShortFilter, (int) bRet) ;
1214: SetDlgItemText(hwndMainDialog, ID_RETURNO, szTemp) ;
1215:
1216: InterpretCustomFilterString() ;
1217:
1218: FillOpenDlg(hwndMainDialog, po) ;
1219:
1220: if (hDialog)
1221: {
1222: FreeResource(hDialog) ; //free ofn.hInstance
1223: hDialog = (HANDLE) 0 ;
1224: hRes = (HANDLE) 0 ;
1225: }
1226: }
1227:
1228:
1229:
1230:
1231:
1232:
1233:
1234: /************************************************************************
1235:
1236: Function: OpenMultiThreadEnableButtons(BOOL, HWND)
1237:
1238: Purpose:
1239:
1240: Enable or disable the buttons that might affect the state of the
1241: OPENFILENAME structures. This is necessary because during a
1242: multithreading session, these buttons may be accessible even though
1243: there are Open dialogs still working and we don't want to change
1244: the OPENFILENAME structure out from under them.
1245:
1246:
1247: Returns: Nothing.
1248:
1249: Comments:
1250:
1251: ************************************************************************/
1252:
1253: void OpenMultiThreadEnableButtons(BOOL bEnable, HWND hwnd)
1254: {
1255: EnableWindow(GetDlgItem(hwnd, IDOK), bEnable) ;
1256: EnableWindow(GetDlgItem(hwnd, IDCANCEL), bEnable) ;
1257: EnableWindow(GetDlgItem(hwnd, ID_RESETOPEN), bEnable) ;
1258: EnableWindow(GetDlgItem(hwnd, ID_MULTIOPEN), bEnable) ;
1259: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.