2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 #include <afs/param.h>
19 #include <WINNT/subclass.h>
20 #include <WINNT/talocale.h>
21 #include <WINNT/dialog.h>
22 #include <WINNT/fastlist.h>
24 #ifdef FORWARD_WM_COMMAND
25 #undef FORWARD_WM_COMMAND
27 #define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \
28 (fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))
32 * MISCELLANEOUS ______________________________________________________________
37 #define REALLOC(_a,_c,_r,_i) DialogReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
38 BOOL
DialogReallocFunction (LPVOID
*ppTarget
, size_t cbElement
, size_t *pcTarget
, size_t cReq
, size_t cInc
)
43 if (cReq
<= *pcTarget
)
46 if ((cNew
= cInc
* ((cReq
+ cInc
-1) / cInc
)) <= 0)
49 if ((pNew
= (LPVOID
)Allocate (cbElement
* cNew
)) == NULL
)
51 memset (pNew
, 0x00, cbElement
* cNew
);
55 memcpy (pNew
, *ppTarget
, cbElement
* (*pcTarget
));
66 void DialogGetRectInParent (HWND hWnd
, RECT
*pr
)
70 GetWindowRect (hWnd
, pr
);
72 pr
->right
-= pr
->left
;
73 pr
->bottom
-= pr
->top
; // right/bottom == width/height for now
78 ScreenToClient (GetParent (hWnd
), &pt
);
82 pr
->right
+= pr
->left
;
83 pr
->bottom
+= pr
->top
;
88 * PROPERTY SHEETS ____________________________________________________________
92 BOOL
PropSheet_HandleNotify (HWND hDlg
, UINT msg
, WPARAM wp
, LPARAM lp
)
97 switch (((NMHDR FAR
*)lp
)->code
)
100 FORWARD_WM_COMMAND (hDlg
, IDOK
, 0, 0, SendMessage
);
103 FORWARD_WM_COMMAND (hDlg
, IDAPPLY
, 0, 0, SendMessage
);
106 FORWARD_WM_COMMAND (hDlg
, IDHELP
, 0, 0, SendMessage
);
109 FORWARD_WM_COMMAND (hDlg
, IDINIT
, wp
, lp
, SendMessage
);
112 FORWARD_WM_COMMAND (hDlg
, IDCANCEL
, 0, 0, SendMessage
);
128 } *aPropSheets
= NULL
;
130 static size_t cPropSheets
= 0;
133 HRESULT CALLBACK
PropTab_HookProc (HWND hDlg
, UINT msg
, WPARAM wp
, LPARAM lp
)
135 if (PropSheet_HandleNotify (hDlg
, msg
, wp
, lp
))
138 HWND hSheet
= GetParent (hDlg
);
139 HWND hTab
= GetDlgItem (hSheet
, IDC_PROPSHEET_TABCTRL
);
144 for (ii
= 0; ii
< cPropSheets
; ++ii
)
146 if (aPropSheets
[ii
].fInUse
&& (aPropSheets
[ii
].hSheet
== hSheet
))
149 if (ii
>= cPropSheets
)
151 for (size_t ii
= 0; ii
< cPropSheets
; ++ii
)
153 if (aPropSheets
[ii
].fInUse
&& !aPropSheets
[ii
].hSheet
)
155 aPropSheets
[ii
].hSheet
= hSheet
;
160 if (ii
< cPropSheets
)
163 for (iTab
= 0; iTab
< aPropSheets
[ii
].psh
->cTabs
; ++iTab
)
165 if (aPropSheets
[ii
].psh
->aTabs
[iTab
].hDlg
== hDlg
)
168 if (iTab
== aPropSheets
[ii
].psh
->cTabs
)
170 iTab
= (size_t)TabCtrl_GetCurSel (hTab
);
172 if (iTab
< aPropSheets
[ii
].psh
->cTabs
)
174 aPropSheets
[ii
].psh
->aTabs
[iTab
].hDlg
= hDlg
;
175 BOOL rc
= (CallWindowProc ((WNDPROC
)(aPropSheets
[ ii
].psh
->aTabs
[ iTab
].dlgproc
), hDlg
, msg
, wp
, lp
)?TRUE
:FALSE
);
180 ++ aPropSheets
[ ii
].cRef
;
184 if (!(-- aPropSheets
[ ii
].cRef
))
186 PropSheet_Free (aPropSheets
[ ii
].psh
);
187 aPropSheets
[ ii
].fInUse
= FALSE
;
197 return DefWindowProc (hDlg
, msg
, wp
, lp
);
202 LPPROPSHEET
PropSheet_Create (LONG idsTitle
, BOOL fContextHelp
, HWND hParent
, LPARAM lp
)
204 LPPROPSHEET psh
= New (PROPSHEET
);
205 memset (psh
, 0x00, sizeof(PROPSHEET
));
206 psh
->sh
.dwSize
= sizeof(PROPSHEETHEADER
);
207 psh
->sh
.dwFlags
= PSH_MODELESS
| ((fContextHelp
) ? PSH_HASHELP
: 0);
208 psh
->sh
.hwndParent
= hParent
;
209 psh
->sh
.hInstance
= THIS_HINST
;
210 psh
->sh
.pszCaption
= (HIWORD(idsTitle
)) ? (LPTSTR
)(LONG_PTR
)idsTitle
: FormatString(TEXT("%1"),TEXT("%m"),idsTitle
);
211 psh
->fMadeCaption
= (HIWORD(idsTitle
)) ? FALSE
: TRUE
;
216 LPPROPSHEET
PropSheet_Create (int idsTitle
, BOOL fContextHelp
, HWND hParent
, LPARAM lp
)
218 return PropSheet_Create ((LONG
)idsTitle
, fContextHelp
, hParent
, lp
);
221 LPPROPSHEET
PropSheet_Create (LPTSTR pszTitle
, BOOL fContextHelp
, HWND hParent
, LPARAM lp
)
223 return PropSheet_Create ((LONG
)(LONG_PTR
)pszTitle
, fContextHelp
, hParent
, lp
);
227 BOOL
PropSheet_AddTab (LPPROPSHEET psh
, LONG idsTitle
, int idd
, DLGPROC dlgproc
, LPARAM lpUser
, BOOL fHelpButton
, BOOL fStartPage
)
229 TCHAR szTitle
[ cchRESOURCE
];
232 memset (&psp
, 0x00, sizeof(psp
));
233 psp
.dwSize
= sizeof(PROPSHEETPAGE
);
234 psp
.dwFlags
= PSP_DEFAULT
| PSP_DLGINDIRECT
| (fHelpButton
? PSP_HASHELP
: 0);
235 psp
.pResource
= TaLocale_GetDialogResource (idd
, &psp
.hInstance
);
236 psp
.pfnDlgProc
= (DLGPROC
)PropTab_HookProc
;
239 // When first creating the PROPSHEET structure, we had to guess about
240 // which module the tabs would be coming from. Now that we have at least
241 // one tab, we can correct that guess.
243 psh
->sh
.hInstance
= psp
.hInstance
;
245 if (HIWORD(idsTitle
))
247 psp
.pszTitle
= (LPTSTR
)(LONG_PTR
)idsTitle
;
248 psp
.dwFlags
|= PSP_USETITLE
;
250 else if (idsTitle
!= 0)
252 GetString (szTitle
, idsTitle
);
253 psp
.pszTitle
= szTitle
;
254 psp
.dwFlags
|= PSP_USETITLE
;
258 if ((hp
= CreatePropertySheetPage (&psp
)) == 0)
261 size_t size
= psh
->sh
.nPages
;
262 if (!REALLOC( psh
->sh
.phpage
, size
, 1+psh
->sh
.nPages
, 1))
265 psh
->sh
.nPages
= (UINT
) size
;
266 if (!REALLOC( psh
->aTabs
, psh
->cTabs
, psh
->sh
.nPages
, 1))
269 psh
->aTabs
[ psh
->sh
.nPages
-1 ].dlgproc
= dlgproc
;
270 psh
->aTabs
[ psh
->sh
.nPages
-1 ].lpUser
= lpUser
;
271 psh
->aTabs
[ psh
->sh
.nPages
-1 ].hDlg
= 0;
273 psh
->sh
.phpage
[ psh
->sh
.nPages
-1 ] = hp
;
275 psh
->sh
.nStartPage
= psh
->sh
.nPages
-1;
280 BOOL
PropSheet_AddTab (LPPROPSHEET psh
, int idsTitle
, int idd
, DLGPROC dlgproc
, LPARAM lpUser
, BOOL fHelpButton
, BOOL fStartPage
)
282 return PropSheet_AddTab (psh
, (LONG
)idsTitle
, idd
, dlgproc
, lpUser
, fHelpButton
, fStartPage
);
285 BOOL
PropSheet_AddTab (LPPROPSHEET psh
, LPTSTR pszTitle
, int idd
, DLGPROC dlgproc
, LPARAM lpUser
, BOOL fHelpButton
, BOOL fStartPage
)
287 return PropSheet_AddTab (psh
, (LONG
)(LONG_PTR
)pszTitle
, idd
, dlgproc
, lpUser
, fHelpButton
, fStartPage
);
291 void PropSheet_NotifyAllTabs (LPPROPSHEET psh
, HWND hDlg
, UINT msg
)
293 for (size_t ii
= 0; ii
< psh
->cTabs
; ++ii
)
295 if (psh
->aTabs
[ ii
].dlgproc
)
297 CallWindowProc ((WNDPROC
)(psh
->aTabs
[ ii
].dlgproc
), hDlg
, msg
, (WPARAM
)psh
, psh
->aTabs
[ ii
].lpUser
);
303 HRESULT CALLBACK
PropSheet_HookProc (HWND hSheet
, UINT msg
, WPARAM wp
, LPARAM lp
)
305 PVOID oldproc
= Subclass_FindNextHook (hSheet
, PropSheet_HookProc
);
309 rc
= CallWindowProc ((WNDPROC
)oldproc
, hSheet
, msg
, wp
, lp
);
311 rc
= DefWindowProc (hSheet
, msg
, wp
, lp
);
317 for (ii
= 0; ii
< cPropSheets
; ++ii
)
319 if (aPropSheets
[ii
].fInUse
&& (aPropSheets
[ii
].hSheet
== hSheet
))
322 if (ii
< cPropSheets
)
324 for (size_t iTab
= 0; iTab
< aPropSheets
[ii
].psh
->cTabs
; ++iTab
)
326 if ( (aPropSheets
[ii
].psh
->aTabs
[iTab
].hDlg
) &&
327 (IsWindow (aPropSheets
[ii
].psh
->aTabs
[iTab
].hDlg
)) &&
328 (aPropSheets
[ii
].psh
->aTabs
[iTab
].dlgproc
!= NULL
) )
330 DestroyWindow (aPropSheets
[ii
].psh
->aTabs
[iTab
].hDlg
);
334 PropSheet_NotifyAllTabs (aPropSheets
[ ii
].psh
, hSheet
, WM_DESTROY_SHEET
);
336 if (!(-- aPropSheets
[ ii
].cRef
))
338 PropSheet_Free (aPropSheets
[ ii
].psh
);
339 aPropSheets
[ ii
].fInUse
= FALSE
;
343 Subclass_RemoveHook (hSheet
, PropSheet_HookProc
);
351 LPARAM
PropSheet_FindTabParam (HWND hTab
)
354 for (ii
= 0; ii
< cPropSheets
; ++ii
)
356 if (aPropSheets
[ii
].fInUse
&& (aPropSheets
[ii
].hSheet
== hTab
))
357 return aPropSheets
[ii
].psh
->lpUser
;
360 HWND hSheet
= GetParent (hTab
);
361 for (ii
= 0; ii
< cPropSheets
; ++ii
)
363 if (aPropSheets
[ii
].fInUse
&& (aPropSheets
[ii
].hSheet
== hSheet
))
366 if (ii
< cPropSheets
)
368 for (size_t iTab
= 0; iTab
< aPropSheets
[ ii
].psh
->cTabs
; ++iTab
)
370 if (hTab
== aPropSheets
[ ii
].psh
->aTabs
[ iTab
].hDlg
)
371 return aPropSheets
[ ii
].psh
->aTabs
[ iTab
].lpUser
;
379 BOOL
PropSheet_ShowModal (LPPROPSHEET psh
, void (*fnPump
)(MSG
*lpm
))
382 if ((hSheet
= PropSheet_ShowModeless (psh
, SW_SHOW
)) == NULL
)
385 BOOL fWasEnabled
= TRUE
;
386 HWND hParent
= psh
->sh
.hwndParent
;
387 if (hParent
&& IsWindow (hParent
))
389 fWasEnabled
= IsWindowEnabled (hParent
);
390 EnableWindow (hParent
, FALSE
);
394 while (GetMessage (&msg
, NULL
, 0, 0))
396 if (IsMemoryManagerMessage (&msg
))
399 if (!PropSheet_GetCurrentPageHwnd (hSheet
))
401 if (hParent
&& IsWindow (hParent
))
402 EnableWindow (hParent
, fWasEnabled
);
403 DestroyWindow (hSheet
);
406 if (!IsWindow (hSheet
))
412 TranslateMessage (&msg
);
413 DispatchMessage (&msg
);
418 if (PropSheet_IsDialogMessage (hSheet
, &msg
))
425 TranslateMessage (&msg
);
426 DispatchMessage (&msg
);
430 if (hParent
&& IsWindow (hParent
))
431 EnableWindow (hParent
, fWasEnabled
);
437 HWND
PropSheet_ShowModeless (LPPROPSHEET psh
, int nCmdShow
)
439 // Write down that we're opening a property sheet. Since we
440 // don't know the window handle yet, we'll set it to zero--
441 // when PropSheetTab_HookProc gets called for a property sheet
442 // that doesn't seem to be listed, it will write down hSheet for us.
443 // This way, we get the aPropSheets[] array filled in--complete with
444 // window handle--*before* the tabs themselves get any messages.
445 // Otherwise, we'd have to wait until the WM_INITDIALOG/IDINIT
446 // messages were finished.
449 for (ii
= 0; ii
< cPropSheets
; ++ii
)
451 if (!aPropSheets
[ ii
].fInUse
)
454 if (!REALLOC (aPropSheets
, cPropSheets
, 1+ii
, 4))
456 aPropSheets
[ ii
].fInUse
= TRUE
;
457 aPropSheets
[ ii
].hSheet
= 0;
458 aPropSheets
[ ii
].psh
= psh
;
459 aPropSheets
[ ii
].cRef
= 1;
461 // Open the property sheet dialog.
463 psh
->sh
.dwFlags
|= PSH_MODELESS
;
466 if ((hSheet
= (HWND
)PropertySheet (&psh
->sh
)) == NULL
)
469 // Tell all tabs (not just the first one) that the sheet has been
470 // created. We'll also want to hook the sheet itself here, so we can
471 // clean up when it's destroyed.
473 Subclass_AddHook (hSheet
, PropSheet_HookProc
);
474 PropSheet_NotifyAllTabs (psh
, hSheet
, WM_INITDIALOG_SHEET
);
475 ShowWindow (hSheet
, nCmdShow
);
481 void PropSheet_Free (LPPROPSHEET psh
)
487 Free (psh
->sh
.phpage
);
489 if (psh
->fMadeCaption
&& psh
->sh
.pszCaption
)
491 FreeString (psh
->sh
.pszCaption
);
503 HWND
PropSheet_FindTabWindow (LPPROPSHEET psh
, DLGPROC dlgproc
)
507 for (size_t iTab
= 0; iTab
< psh
->cTabs
; ++iTab
)
509 if (dlgproc
== psh
->aTabs
[ iTab
].dlgproc
)
510 return psh
->aTabs
[ iTab
].hDlg
;
517 void PropSheetChanged (HWND hDlg
)
519 PropSheet_Changed (GetParent(hDlg
), hDlg
);
523 void TabCtrl_SwitchToTab (HWND hTab
, int iTab
)
525 TabCtrl_SetCurSel (hTab
, iTab
);
529 nm
.idFrom
= IDC_PROPSHEET_TABCTRL
;
530 nm
.code
= TCN_SELCHANGE
;
531 SendMessage (GetParent (hTab
), WM_NOTIFY
, 0, (LPARAM
)&nm
);
536 * LISTVIEW ___________________________________________________________________
540 LPARAM
FL_StartChange (HWND hList
, BOOL fReset
)
542 LPARAM dwSelected
= FL_GetSelectedData (hList
);
543 FastList_Begin (hList
);
545 FastList_RemoveAll (hList
);
550 void FL_EndChange (HWND hList
, LPARAM lpToSelect
)
553 FL_SetSelectedByData (hList
, lpToSelect
);
554 FastList_EndAll (hList
);
558 void FL_ResizeColumns (HWND hList
, WORD nCols
, WORD
*acx
)
560 for (WORD ii
= 0; ii
< nCols
; ++ii
)
563 FastList_GetColumn (hList
, ii
, &flc
);
565 flc
.cxWidth
= acx
[ ii
];
566 FastList_SetColumn (hList
, ii
, &flc
);
571 void cdecl FL_SetColumns (HWND hList
, WORD nCols
, WORD
*acx
, ...)
576 for (WORD ii
= 0; ii
< nCols
; ii
++)
579 GetString (flc
.szText
, va_arg (arg
, WORD
));
580 flc
.dwFlags
= FLCF_JUSTIFY_LEFT
;
581 flc
.cxWidth
= acx
[ ii
]; // width of the column, in pixels
582 FastList_SetColumn (hList
, ii
, &flc
);
587 void FL_GetColumns (HWND hList
, WORD nCols
, WORD
*acx
)
589 for (WORD ii
= 0; ii
< nCols
; ii
++)
592 FastList_GetColumn (hList
, ii
, &flc
);
593 acx
[ ii
] = (WORD
)flc
.cxWidth
;
598 HLISTITEM
cdecl FL_AddItem (HWND hList
, WORD nCols
, LPARAM lp
, int iImage1
, ...)
601 va_start (arg
, iImage1
);
603 FASTLISTADDITEM flai
;
604 memset (&flai
, 0x00, sizeof(flai
));
606 flai
.iFirstImage
= iImage1
;
607 flai
.iSecondImage
= IMAGE_NOIMAGE
;
608 flai
.pszText
= va_arg (arg
, LPTSTR
);
612 FastList_Begin (hList
);
615 if ((hItem
= FastList_AddItem (hList
, &flai
)) != NULL
)
617 for (WORD ii
= 1; ii
< nCols
; ii
++)
619 FastList_SetItemText (hList
, hItem
, ii
, va_arg (arg
, LPTSTR
));
623 FastList_End (hList
);
628 void FL_GetItemText (HWND hList
, HLISTITEM hItem
, int iCol
, LPTSTR psz
)
630 LPCTSTR pszText
= FastList_GetItemText (hList
, hItem
, iCol
);
634 lstrcpy (psz
, pszText
);
638 void FL_SetItemText (HWND hList
, HLISTITEM hItem
, int iCol
, LPCTSTR psz
)
640 FastList_SetItemText (hList
, hItem
, iCol
, psz
);
644 void FL_SetSelectedByData (HWND hList
, LPARAM lp
)
647 if ((hItem
= FastList_FindItem (hList
, lp
)) != NULL
)
649 FL_SetSelected (hList
, hItem
);
654 void FL_SetSelected (HWND hList
, HLISTITEM hItem
)
656 FastList_Begin (hList
);
657 FastList_SelectNone (hList
);
660 FastList_SelectItem (hList
, hItem
, TRUE
);
661 FastList_EnsureVisible (hList
, hItem
);
663 FastList_SetFocus (hList
, hItem
);
664 FastList_End (hList
);
668 HLISTITEM
FL_GetSelected (HWND hList
, HLISTITEM hItem
)
670 return FastList_FindNextSelected (hList
, hItem
);
674 HLISTITEM
FL_GetFocused (HWND hList
)
676 return FastList_GetFocus (hList
);
680 LPARAM
FL_GetFocusedData (HWND hList
)
683 if ((hItem
= FastList_GetFocus (hList
)) == NULL
)
686 return FastList_GetItemParam (hList
, hItem
);
690 LPARAM
FL_GetData (HWND hList
, HLISTITEM hItem
)
692 return FastList_GetItemParam (hList
, hItem
);
696 HLISTITEM
FL_GetIndex (HWND hList
, LPARAM lp
)
698 return FastList_FindItem (hList
, lp
);
702 LPARAM
FL_GetSelectedData (HWND hList
)
705 if ((hItem
= FastList_FindFirstSelected (hList
)) == NULL
)
708 return FastList_GetItemParam (hList
, hItem
);
712 void FL_RestoreView (HWND hList
, LPVIEWINFO lpvi
)
714 FastList_Begin (hList
);
716 for (size_t cColumns
= FastList_GetColumnCount(hList
); cColumns
; --cColumns
)
718 FastList_RemoveColumn (hList
, cColumns
-1);
721 for (size_t ii
= 0; ii
< lpvi
->nColsShown
; ++ii
)
723 if (lpvi
->aColumns
[ ii
] >= lpvi
->nColsAvail
)
726 size_t iColumn
= lpvi
->aColumns
[ ii
];
729 GetString (flc
.szText
, lpvi
->idsColumns
[ iColumn
]);
731 flc
.dwFlags
= (lpvi
->cxColumns
[ iColumn
] & COLUMN_RIGHTJUST
) ? FLCF_JUSTIFY_RIGHT
: (lpvi
->cxColumns
[ iColumn
] & COLUMN_CENTERJUST
) ? FLCF_JUSTIFY_CENTER
: FLCF_JUSTIFY_LEFT
;
732 flc
.cxWidth
= (lpvi
->cxColumns
[ iColumn
] & (~COLUMN_JUSTMASK
));
733 FastList_SetColumn (hList
, ii
, &flc
);
736 // Restore the fastlist's sort style
738 FastList_SetSortStyle (hList
, (lpvi
->iSort
& (~COLUMN_SORTREV
)), !!(lpvi
->iSort
& COLUMN_SORTREV
));
740 // Switch the FastList into the proper mode--Large Icons,
741 // Small Icons, List or Details.
743 LONG dw
= GetWindowLong (hList
, GWL_STYLE
);
744 dw
&= ~FLS_VIEW_MASK
;
746 SetWindowLong (hList
, GWL_STYLE
, dw
);
748 FastList_End (hList
);
752 void FL_StoreView (HWND hList
, LPVIEWINFO lpvi
)
754 // First, remember what mode the the FastList is in--Large,
755 // Small, List, Tree, or TreeList.
757 lpvi
->lvsView
= GetWindowLong (hList
, GWL_STYLE
);
758 lpvi
->lvsView
&= FLS_VIEW_MASK
;
760 // Record the fastlist's sort style
764 FastList_GetSortStyle (hList
, &iCol
, &fRev
);
765 lpvi
->iSort
= (size_t)iCol
;
767 lpvi
->iSort
|= COLUMN_SORTREV
;
769 // Then remember the columns' widths; we expect that the columns
770 // which are shown (ie, nColsShown and aColumns[]) are up-to-date
773 if (lpvi
->lvsView
& FLS_VIEW_LIST
)
775 for (size_t ii
= 0; ii
< lpvi
->nColsShown
; ++ii
)
777 if (lpvi
->aColumns
[ ii
] >= lpvi
->nColsAvail
)
780 size_t iColumn
= lpvi
->aColumns
[ii
];
782 int dwJust
= (lpvi
->cxColumns
[ iColumn
] & COLUMN_JUSTMASK
);
785 FastList_GetColumn (hList
, ii
, &flc
);
786 lpvi
->cxColumns
[ iColumn
] = flc
.cxWidth
| dwJust
;
792 HLISTITEM
cdecl FL_AddItem (HWND hList
, LPVIEWINFO lpvi
, LPARAM lp
, int iImage1
, ...)
795 va_start (arg
, iImage1
);
797 LPTSTR apszColumns
[ nCOLUMNS_MAX
];
799 for (iColumn
= 0; iColumn
< lpvi
->nColsAvail
; ++iColumn
)
801 apszColumns
[ iColumn
] = va_arg (arg
, LPTSTR
);
804 FastList_Begin (hList
);
806 HLISTITEM hItem
= NULL
;
807 for (size_t ii
= 0; ii
< lpvi
->nColsShown
; ++ii
)
809 if ((iColumn
= lpvi
->aColumns
[ ii
]) >= lpvi
->nColsAvail
)
814 FASTLISTADDITEM flai
;
815 memset (&flai
, 0x00, sizeof(flai
));
817 flai
.iFirstImage
= iImage1
;
818 flai
.iSecondImage
= IMAGE_NOIMAGE
;
819 flai
.pszText
= apszColumns
[ iColumn
];
823 hItem
= FastList_AddItem (hList
, &flai
);
827 FastList_SetItemText (hList
, hItem
, (int)ii
, apszColumns
[ (int)iColumn
]);
831 FastList_End (hList
);
836 BOOL
FL_HitTestForHeaderBar (HWND hList
, POINT ptClient
)
839 for (hHeader
= GetWindow (hList
, GW_CHILD
);
841 hHeader
= GetWindow (hHeader
, GW_HWNDNEXT
))
843 TCHAR szClassName
[ cchRESOURCE
];
845 if (GetClassName (hHeader
, szClassName
, cchRESOURCE
))
847 if (!lstrcmp (szClassName
, WC_HEADER
))
852 if (hHeader
&& IsWindow(hHeader
) && IsWindowVisible(hHeader
))
855 DialogGetRectInParent (hHeader
, &rHeader
);
856 if (PtInRect (&rHeader
, ptClient
))
866 * LISTVIEW ___________________________________________________________________
870 LPARAM
LV_StartChange (HWND hList
, BOOL fReset
)
872 LPARAM dwSelected
= LV_GetSelectedData (hList
);
873 SendMessage (hList
, WM_SETREDRAW
, FALSE
, 0);
875 ListView_DeleteAllItems (hList
);
880 void LV_EndChange (HWND hList
, LPARAM lpToSelect
)
882 SendMessage (hList
, WM_SETREDRAW
, TRUE
, 0);
884 if (lpToSelect
!= (LPARAM
)NULL
)
885 LV_SetSelectedByData (hList
, lpToSelect
);
889 void LV_ResizeColumns (HWND hList
, WORD nCols
, WORD
*acx
)
891 for (WORD ii
= 0; ii
< nCols
; ++ii
)
893 ListView_SetColumnWidth (hList
, ii
, acx
[ ii
]);
897 void cdecl LV_SetColumns (HWND hList
, WORD nCols
, WORD
*acx
, ...)
902 for (WORD ii
= 0; ii
< nCols
; ii
++)
905 TCHAR text
[ cchRESOURCE
];
907 GetString (text
, va_arg (arg
, WORD
));
909 lvC
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
| LVCF_SUBITEM
;
910 lvC
.fmt
= LVCFMT_LEFT
;
912 lvC
.cx
= acx
[ ii
]; // width of the column, in pixels
914 ListView_InsertColumn (hList
, ii
, &lvC
);
919 void LV_GetColumns (HWND hList
, WORD nCols
, WORD
*acx
)
921 for (WORD ii
= 0; ii
< nCols
; ii
++)
923 acx
[ ii
] = ListView_GetColumnWidth (hList
, ii
);
928 void cdecl LV_AddItem (HWND hList
, WORD nCols
, int index
, LPARAM lp
, int iImage
, ...)
932 va_start (arg
, iImage
);
934 lvI
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
939 lvI
.pszText
= va_arg (arg
, LPTSTR
);
940 lvI
.cchTextMax
= cchRESOURCE
;
944 if ((index
== INDEX_SORT
) && (lvI
.pszText
!= LPSTR_TEXTCALLBACK
))
946 lvI
.iItem
= LV_PickInsertionPoint (hList
, lvI
.pszText
);
949 DWORD dw
= ListView_InsertItem (hList
, &lvI
);
951 for (WORD ii
= 1; ii
< nCols
; ii
++)
953 ListView_SetItemText (hList
, dw
, ii
, va_arg (arg
, LPTSTR
));
958 void cdecl LV_GetItemText (HWND hList
, int index
, short col
, LPTSTR psz
)
961 ListView_GetItemText (hList
, index
, col
, (LPTSTR
)psz
, cchRESOURCE
);
965 void cdecl LV_SetItemText (HWND hList
, int index
, short col
, LPCTSTR psz
)
967 ListView_SetItemText (hList
, index
, col
, (LPTSTR
)psz
);
971 void LV_SetSelectedByData (HWND hList
, LPARAM lp
)
975 if ((index
= LV_GetIndex (hList
, lp
)) != -1)
977 LV_SetSelected (hList
, index
);
982 void LV_SetSelected (HWND hList
, int index
)
984 ListView_EnsureVisible (hList
, index
, FALSE
);
986 ListView_SetItemState (hList
, index
, LVIS_SELECTED
| LVIS_FOCUSED
, LVIS_SELECTED
| LVIS_FOCUSED
);
990 int LV_GetSelected (HWND hList
, int index
)
992 return ListView_GetNextItem (hList
, index
, LVNI_SELECTED
);
996 int LV_GetFocused (HWND hList
)
998 return ListView_GetNextItem (hList
, -1, LVNI_FOCUSED
);
1002 LPARAM
LV_GetFocusedData (HWND hList
)
1006 if ((idxFocus
= LV_GetFocused (hList
)) == -1)
1009 return LV_GetData (hList
, idxFocus
);
1013 LPARAM
LV_GetData (HWND hList
, int index
)
1017 memset (&lvI
, 0x00, sizeof(LV_ITEM
));
1018 lvI
.mask
= LVIF_PARAM
;
1021 if (! ListView_GetItem (hList
, &lvI
))
1028 int LV_GetIndex (HWND hList
, LPARAM lp
)
1032 memset (&lvfi
, 0x00, sizeof(lvfi
));
1034 lvfi
.flags
= LVFI_PARAM
;
1037 return ListView_FindItem (hList
, -1, &lvfi
);
1041 LPARAM
LV_GetSelectedData (HWND hList
)
1045 if ((index
= LV_GetSelected (hList
)) == -1)
1048 return LV_GetData (hList
, index
);
1052 void LV_RestoreView (HWND hList
, LPVIEWINFO lpvi
)
1054 // Add columns to the listview; remember that we'll have to remove any
1055 // existing columns first.
1057 while (ListView_DeleteColumn (hList
, 0))
1060 for (size_t ii
= 0; ii
< lpvi
->nColsShown
; ++ii
)
1062 if (lpvi
->aColumns
[ ii
] >= lpvi
->nColsAvail
)
1065 size_t iColumn
= lpvi
->aColumns
[ii
];
1069 TCHAR szText
[ cchRESOURCE
];
1070 GetString (szText
, lpvi
->idsColumns
[ iColumn
]);
1072 lvc
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
| LVCF_SUBITEM
;
1073 lvc
.fmt
= (lpvi
->cxColumns
[ iColumn
] & COLUMN_RIGHTJUST
) ? LVCFMT_RIGHT
: (lpvi
->cxColumns
[ iColumn
] & COLUMN_CENTERJUST
) ? LVCFMT_CENTER
: LVCFMT_LEFT
;
1074 lvc
.pszText
= szText
;
1075 lvc
.cx
= (lpvi
->cxColumns
[ iColumn
] & (~COLUMN_JUSTMASK
));
1076 lvc
.iSubItem
= (int)ii
;
1077 ListView_InsertColumn (hList
, ii
, &lvc
);
1080 // Switch the ListView into the proper mode--Large Icons,
1081 // Small Icons, List or Details.
1083 LONG dw
= GetWindowLong (hList
, GWL_STYLE
);
1084 dw
&= ~LVS_TYPEMASK
;
1085 dw
|= lpvi
->lvsView
;
1086 dw
|= LVS_AUTOARRANGE
;
1087 SetWindowLong (hList
, GWL_STYLE
, dw
);
1088 ListView_Arrange (hList
, LVA_DEFAULT
);
1092 void LV_StoreView (HWND hList
, LPVIEWINFO lpvi
)
1094 // First, remember what mod the the ListView is in--Large Icons,
1095 // Small Icons, List or Details.
1097 lpvi
->lvsView
= GetWindowLong (hList
, GWL_STYLE
);
1098 lpvi
->lvsView
&= LVS_TYPEMASK
;
1100 // Then remember the columns' widths; we expect that the columns
1101 // which are shown (ie, nColsShown and aColumns[]) are up-to-date
1104 if (lpvi
->lvsView
== LVS_REPORT
)
1106 for (size_t ii
= 0; ii
< lpvi
->nColsShown
; ++ii
)
1108 if (lpvi
->aColumns
[ ii
] >= lpvi
->nColsAvail
)
1111 size_t iColumn
= lpvi
->aColumns
[ii
];
1113 int dwJust
= (lpvi
->cxColumns
[ iColumn
] & COLUMN_JUSTMASK
);
1115 lpvi
->cxColumns
[ iColumn
] = ListView_GetColumnWidth (hList
, ii
);
1116 lpvi
->cxColumns
[ iColumn
] |= dwJust
;
1122 typedef struct // VIEWSORTINFO
1128 } VIEWSORTINFO
, *LPVIEWSORTINFO
;
1130 HRESULT CALLBACK
LV_SortView_Numeric (LPARAM lp1
, LPARAM lp2
, LPARAM lpSort
)
1132 LPVIEWSORTINFO lpvsi
= (LPVIEWSORTINFO
)lpSort
;
1133 TCHAR szText
[ cchRESOURCE
];
1137 int ii1
= LV_GetIndex (lpvsi
->hList
, lp1
);
1138 int ii2
= LV_GetIndex (lpvsi
->hList
, lp2
);
1140 LV_GetItemText (lpvsi
->hList
, ii1
, (short)lpvsi
->iColSort
, szText
);
1143 LV_GetItemText (lpvsi
->hList
, ii2
, (short)lpvsi
->iColSort
, szText
);
1146 if (lpvsi
->fAscending
)
1147 return (HRESULT
)((d2
< d1
) ? -1 : (d2
== d1
) ? 0 : 1);
1149 return (HRESULT
)((d1
< d2
) ? -1 : (d1
== d2
) ? 0 : 1);
1153 HRESULT CALLBACK
LV_SortView_Alphabetic (LPARAM lp1
, LPARAM lp2
, LPARAM lpSort
)
1155 LPVIEWSORTINFO lpvsi
= (LPVIEWSORTINFO
)lpSort
;
1156 TCHAR szText1
[ cchRESOURCE
];
1157 TCHAR szText2
[ cchRESOURCE
];
1159 int ii1
= LV_GetIndex (lpvsi
->hList
, lp1
);
1160 int ii2
= LV_GetIndex (lpvsi
->hList
, lp2
);
1162 LV_GetItemText (lpvsi
->hList
, ii1
, (short)lpvsi
->iColSort
, szText1
);
1163 LV_GetItemText (lpvsi
->hList
, ii2
, (short)lpvsi
->iColSort
, szText2
);
1165 if (lpvsi
->fAscending
)
1166 return lstrcmp (szText2
, szText1
);
1168 return lstrcmp (szText1
, szText2
);
1172 void LV_SortView (HWND hList
, LPVIEWINFO lpvi
)
1175 for (iColSort
= 0; iColSort
< lpvi
->nColsShown
; ++iColSort
)
1177 if ((lpvi
->iSort
& (~COLUMN_SORTREV
)) == lpvi
->aColumns
[ iColSort
])
1181 if (iColSort
< lpvi
->nColsShown
)
1186 vsi
.iColSort
= iColSort
;
1187 vsi
.fAscending
= (lpvi
->iSort
& COLUMN_SORTREV
) ? TRUE
: FALSE
;
1189 if (lpvi
->cxColumns
[ lpvi
->iSort
] & COLUMN_RIGHTJUST
)
1190 ListView_SortItems (hList
, (PFNLVCOMPARE
)LV_SortView_Numeric
, (LPARAM
)&vsi
);
1192 ListView_SortItems (hList
, (PFNLVCOMPARE
)LV_SortView_Alphabetic
, (LPARAM
)&vsi
);
1197 void cdecl LV_AddItem (HWND hList
, LPVIEWINFO lpvi
, int index
, LPARAM lp
, int iImage
, ...)
1200 va_start (arg
, iImage
);
1202 LPTSTR apszColumns
[ nCOLUMNS_MAX
];
1204 for (iColumn
= 0; iColumn
< lpvi
->nColsAvail
; ++iColumn
)
1206 apszColumns
[ iColumn
] = va_arg (arg
, LPTSTR
);
1209 if ((index
== INDEX_SORT
) && (iColumn
) && (apszColumns
[0] != LPSTR_TEXTCALLBACK
))
1211 index
= LV_PickInsertionPoint (hList
, apszColumns
[0]);
1215 for (size_t ii
= 0; ii
< lpvi
->nColsShown
; ++ii
)
1217 if ((iColumn
= lpvi
->aColumns
[ ii
]) >= lpvi
->nColsAvail
)
1223 lvitem
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
1225 lvitem
.stateMask
= 0;
1226 lvitem
.iItem
= index
;
1227 lvitem
.iSubItem
= 0;
1228 lvitem
.pszText
= apszColumns
[ iColumn
];
1229 lvitem
.cchTextMax
= cchRESOURCE
;
1230 lvitem
.iImage
= iImage
;
1233 dw
= ListView_InsertItem (hList
, &lvitem
);
1237 ListView_SetItemText (hList
, dw
, (int)ii
, apszColumns
[ iColumn
]);
1243 BOOL
LV_HitTestForHeaderBar (HWND hList
, POINT ptClient
)
1246 for (hHeader
= GetWindow (hList
, GW_CHILD
);
1248 hHeader
= GetWindow (hHeader
, GW_HWNDNEXT
))
1250 TCHAR szClassName
[ cchRESOURCE
];
1252 if (GetClassName (hHeader
, szClassName
, cchRESOURCE
))
1254 if (!lstrcmp (szClassName
, WC_HEADER
))
1259 if (hHeader
&& IsWindow(hHeader
) && IsWindowVisible(hHeader
))
1262 DialogGetRectInParent (hHeader
, &rHeader
);
1263 if (PtInRect (&rHeader
, ptClient
))
1271 int LV_PickInsertionPoint (HWND hList
, LPTSTR pszNewItem
, int (__stdcall
*fnSort
)(LPCTSTR
, LPCTSTR
))
1274 int iItemHigh
= ListView_GetItemCount (hList
) -1;
1279 while (iItemLow
<= iItemHigh
)
1281 int iItemTest
= iItemLow
+ (iItemHigh
- iItemLow
) / 2;
1283 TCHAR szItemTest
[ 256 ];
1284 ListView_GetItemText (hList
, iItemTest
, 0, szItemTest
, 256);
1286 int iCompare
= (*fnSort
)(pszNewItem
, szItemTest
);
1289 if ((iItemHigh
= iItemTest
-1) < iItemLow
)
1290 return iItemHigh
+1;
1294 if ((iItemLow
= iItemTest
+1) > iItemHigh
)
1305 * COMBO BOXES ________________________________________________________________
1309 LPARAM
CB_StartChange (HWND hCombo
, BOOL fReset
)
1311 LPARAM dwSelected
= CB_GetSelectedData (hCombo
);
1312 SendMessage (hCombo
, WM_SETREDRAW
, FALSE
, 0);
1314 SendMessage (hCombo
, CB_RESETCONTENT
, 0, 0);
1319 void CB_EndChange (HWND hCombo
, LPARAM lpToSelect
)
1321 SendMessage (hCombo
, WM_SETREDRAW
, TRUE
, 0);
1323 if (lpToSelect
!= (LPARAM
)NULL
)
1324 CB_SetSelectedByData (hCombo
, lpToSelect
);
1328 UINT
CB_AddItem (HWND hCombo
, int nsz
, LPARAM lp
)
1333 psz
= FormatString (nsz
);
1334 rc
= CB_AddItem (hCombo
, psz
, lp
);
1341 UINT
CB_AddItem (HWND hCombo
, LPCTSTR psz
, LPARAM lp
)
1344 if ((index
= (UINT
)SendMessage (hCombo
, CB_ADDSTRING
, 0, (LPARAM
)psz
)) != (UINT
)-1)
1346 SendMessage (hCombo
, CB_SETITEMDATA
, index
, lp
);
1352 void CB_SetSelected (HWND hCombo
, UINT index
)
1354 SendMessage (hCombo
, CB_SETCURSEL
, index
, 0);
1358 void CB_SetSelectedByData (HWND hCombo
, LPARAM lpMatch
)
1360 CB_SetSelected (hCombo
, CB_GetIndex (hCombo
, lpMatch
));
1364 UINT
CB_GetSelected (HWND hCombo
)
1366 return (UINT
)SendMessage (hCombo
, CB_GETCURSEL
, 0, 0);
1370 LPARAM
CB_GetSelectedData (HWND hCombo
)
1374 if ((index
= CB_GetSelected (hCombo
)) == -1)
1377 return CB_GetData (hCombo
, index
);
1381 LPARAM
CB_GetData (HWND hCombo
, UINT index
)
1383 return (LPARAM
)SendMessage (hCombo
, CB_GETITEMDATA
, index
, 0);
1387 UINT
CB_GetIndex (HWND hCombo
, LPARAM lpMatch
)
1389 UINT idxMax
= (UINT
)SendMessage (hCombo
, CB_GETCOUNT
, 0, 0);
1391 for (UINT index
= 0; index
< idxMax
; index
++)
1393 if (SendMessage (hCombo
, CB_GETITEMDATA
, index
, 0) == lpMatch
)
1402 * LIST BOXES _________________________________________________________________
1406 LPARAM
LB_StartChange (HWND hList
, BOOL fReset
)
1408 LPARAM dwSelected
= LB_GetSelectedData (hList
);
1409 SendMessage (hList
, WM_SETREDRAW
, FALSE
, 0);
1411 SendMessage (hList
, LB_RESETCONTENT
, 0, 0);
1416 void LB_EndChange (HWND hList
, LPARAM lpToSelect
)
1418 SendMessage (hList
, WM_SETREDRAW
, TRUE
, 0);
1420 if (lpToSelect
!= (LPARAM
)NULL
)
1421 LB_SetSelectedByData (hList
, lpToSelect
);
1425 UINT
LB_AddItem (HWND hList
, int nsz
, LPARAM lp
)
1430 psz
= FormatString (nsz
);
1431 rc
= LB_AddItem (hList
, psz
, lp
);
1438 UINT
LB_AddItem (HWND hList
, LPCTSTR psz
, LPARAM lp
)
1441 if ((index
= (UINT
)SendMessage (hList
, LB_ADDSTRING
, 0, (LPARAM
)psz
)) != -1)
1443 SendMessage (hList
, LB_SETITEMDATA
, index
, lp
);
1449 void LB_EnsureVisible (HWND hList
, UINT index
)
1452 if ((cyItem
= (int)SendMessage (hList
, LB_GETITEMHEIGHT
, 0, 0)) != 0)
1455 GetClientRect (hList
, &rClient
);
1457 if ((cWindow
= cyRECT(rClient
) / cyItem
) == 0)
1460 int idxTop
= (int)SendMessage (hList
, LB_GETTOPINDEX
, 0, 0);
1461 if (index
< (UINT
)idxTop
)
1463 SendMessage (hList
, LB_SETTOPINDEX
, index
, 0);
1465 else if (index
>= (UINT
)(idxTop
+cWindow
))
1467 SendMessage (hList
, LB_SETTOPINDEX
, index
-cWindow
+1, 0);
1473 void LB_SetSelected (HWND hList
, UINT index
)
1475 SendMessage (hList
, LB_SETCURSEL
, index
, 0);
1476 LB_EnsureVisible (hList
, index
);
1480 void LB_SetSelectedByData (HWND hList
, LPARAM lpMatch
)
1482 LB_SetSelected (hList
, LB_GetIndex (hList
, lpMatch
));
1486 UINT
LB_GetSelected (HWND hList
)
1488 return (UINT
)SendMessage (hList
, LB_GETCURSEL
, 0, 0);
1492 LPARAM
LB_GetSelectedData (HWND hList
)
1496 if ((index
= LB_GetSelected (hList
)) == (UINT
)-1)
1499 return LB_GetData (hList
, index
);
1503 LPARAM
LB_GetData (HWND hList
, UINT index
)
1505 return (LPARAM
)SendMessage (hList
, LB_GETITEMDATA
, index
, 0);
1509 UINT
LB_GetIndex (HWND hList
, LPARAM lpMatch
)
1511 UINT idxMax
= (UINT
)SendMessage (hList
, LB_GETCOUNT
, 0, 0);
1513 for (UINT index
= 0; index
< idxMax
; index
++)
1515 if (SendMessage (hList
, LB_GETITEMDATA
, index
, 0) == lpMatch
)
1523 WORD
LB_GetStringExtent (HWND hList
, LPTSTR pszString
)
1525 HDC hdc
= GetDC (hList
);
1528 GetTextExtentPoint32 (hdc
, pszString
, lstrlen(pszString
), &sz
);
1530 ReleaseDC (hList
, hdc
);
1531 return (WORD
)( sz
.cx
+ 2 * GetSystemMetrics (SM_CXBORDER
) );
1535 HRESULT CALLBACK
ListBox_HScrollHook (HWND hList
, UINT msg
, WPARAM wp
, LPARAM lp
)
1537 PVOID oldProc
= Subclass_FindNextHook (hList
, ListBox_HScrollHook
);
1542 Subclass_RemoveHook (hList
, ListBox_HScrollHook
);
1547 LPTSTR pszString
= (LPTSTR
)lp
;
1548 WORD cxString
= LB_GetStringExtent (hList
, pszString
);
1549 WORD cxExtent
= (WORD
)SendMessage (hList
, LB_GETHORIZONTALEXTENT
, 0, 0);
1550 if (cxString
> cxExtent
)
1551 SendMessage (hList
, LB_SETHORIZONTALEXTENT
, (WPARAM
)cxString
, 0);
1555 case LB_DELETESTRING
:
1557 int iItemSkip
= (int)wp
;
1558 int iItemMax
= (int)SendMessage (hList
, LB_GETCOUNT
, 0, 0);
1562 for (iItem
= 0; iItem
< iItemMax
; iItem
++)
1564 if (iItem
== iItemSkip
)
1566 int cch
= (int)SendMessage (hList
, LB_GETTEXTLEN
, (WPARAM
)iItem
, 0);
1567 cchMax
= max (cch
, cchMax
);
1570 WORD cxExtent
= (WORD
)SendMessage (hList
, LB_GETHORIZONTALEXTENT
, 0, 0);
1571 WORD cxStringMax
= 0;
1572 LPTSTR pszString
= AllocateString (cchMax
+1);
1574 for (iItem
= 0; iItem
< iItemMax
; iItem
++)
1576 if (iItem
== iItemSkip
)
1578 SendMessage (hList
, LB_GETTEXT
, (WPARAM
)iItem
, (LPARAM
)pszString
);
1579 WORD cxString
= LB_GetStringExtent (hList
, pszString
);
1580 cxStringMax
= max (cxString
, cxStringMax
);
1583 FreeString (pszString
);
1584 SendMessage (hList
, LB_SETHORIZONTALEXTENT
, (WPARAM
)cxStringMax
, 0);
1590 return CallWindowProc ((WNDPROC
)oldProc
, hList
, msg
, wp
, lp
);
1592 return DefWindowProc (hList
, msg
, wp
, lp
);
1596 void LB_EnableHScroll (HWND hList
)
1598 Subclass_AddHook (hList
, ListBox_HScrollHook
);
1603 * TREEVIEWS __________________________________________________________________
1607 LPARAM
TV_GetData (HWND hTree
, HTREEITEM hti
)
1612 tvi
.mask
= TVIF_PARAM
;
1614 if (!TreeView_GetItem (hTree
, &tvi
))
1615 return (LPARAM
)NULL
;
1621 LPARAM
TV_GetSelectedData (HWND hTree
)
1623 HTREEITEM hti
= TreeView_GetSelection (hTree
);
1628 return TV_GetData (hTree
, hti
);
1632 LPARAM
TV_StartChange (HWND hTree
, BOOL fReset
)
1634 LPARAM dwSelected
= TV_GetSelectedData (hTree
);
1635 SendMessage (hTree
, WM_SETREDRAW
, FALSE
, 0);
1637 TreeView_DeleteAllItems (hTree
);
1642 void TV_EndChange (HWND hTree
, LPARAM lpToSelect
)
1644 SendMessage (hTree
, WM_SETREDRAW
, TRUE
, 0);
1646 if (lpToSelect
!= NULL
)
1648 HTREEITEM hti
= TV_RecursiveFind (hTree
, TVI_ROOT
, lpToSelect
);
1650 TreeView_SelectItem (hTree
, hti
);
1655 HTREEITEM
TV_RecursiveFind (HWND hTree
, HTREEITEM htiRoot
, LPARAM lpToFind
)
1657 for (HTREEITEM hti
= (htiRoot
== TVI_ROOT
) ? TreeView_GetRoot (hTree
) : TreeView_GetChild (hTree
, htiRoot
);
1659 hti
= TreeView_GetNextSibling (hTree
, hti
))
1661 if (lpToFind
== TV_GetData (hTree
, hti
))
1665 if ((htiFound
= TV_RecursiveFind (hTree
, hti
, lpToFind
)) != NULL
)
1674 * COMMON DIALOGS _____________________________________________________________
1678 BOOL
Browse_Open (HWND hParent
, LPTSTR pszFilename
, LPTSTR pszLastDirectory
, int idsFilter
, int iddTemplate
, LPOFNHOOKPROC lpfnHook
, DWORD lCustData
)
1680 TCHAR szFilter
[ cchRESOURCE
];
1681 GetString (szFilter
, idsFilter
);
1682 TCHAR chFilter
= szFilter
[ lstrlen(szFilter
)-1 ];
1683 for (LPTSTR pszFilter
= szFilter
;
1684 (*pszFilter
) && ((pszFilter
= (LPTSTR
)lstrchr (pszFilter
, chFilter
)) != NULL
);
1687 *pszFilter
= TEXT('\0');
1691 memset (&ofn
, 0x00, sizeof(ofn
));
1692 ofn
.lStructSize
= sizeof(ofn
);
1693 ofn
.hwndOwner
= hParent
;
1694 ofn
.hInstance
= THIS_HINST
;
1695 ofn
.lpstrFilter
= szFilter
;
1696 ofn
.nFilterIndex
= 1;
1697 ofn
.lpstrFile
= pszFilename
;
1698 ofn
.nMaxFile
= MAX_PATH
;
1699 ofn
.Flags
= OFN_HIDEREADONLY
| OFN_PATHMUSTEXIST
| OFN_FILEMUSTEXIST
;
1700 ofn
.lCustData
= lCustData
;
1702 if (iddTemplate
!= 0)
1704 ofn
.lpTemplateName
= MAKEINTRESOURCE( iddTemplate
);
1705 ofn
.Flags
|= OFN_ENABLETEMPLATE
| OFN_EXPLORER
;
1707 if (lpfnHook
!= NULL
)
1709 ofn
.lpfnHook
= lpfnHook
;
1710 ofn
.Flags
|= OFN_ENABLEHOOK
| OFN_EXPLORER
;
1713 TCHAR szPath
[ MAX_PATH
];
1714 GetCurrentDirectory (MAX_PATH
, szPath
);
1715 if (pszLastDirectory
&& *pszLastDirectory
)
1716 SetCurrentDirectory (pszLastDirectory
);
1718 BOOL rc
= GetOpenFileName (&ofn
);
1720 if (pszLastDirectory
)
1721 GetCurrentDirectory (MAX_PATH
, pszLastDirectory
);
1722 SetCurrentDirectory (szPath
);
1728 BOOL
Browse_Save (HWND hParent
, LPTSTR pszFilename
, LPTSTR pszLastDirectory
, int idsFilter
, int iddTemplate
, LPOFNHOOKPROC lpfnHook
, DWORD lCustData
)
1730 TCHAR szFilter
[ cchRESOURCE
];
1731 GetString (szFilter
, idsFilter
);
1732 TCHAR chFilter
= szFilter
[ lstrlen(szFilter
)-1 ];
1733 for (LPTSTR pszFilter
= szFilter
;
1734 (*pszFilter
) && ((pszFilter
= (LPTSTR
)lstrchr (pszFilter
, chFilter
)) != NULL
);
1737 *pszFilter
= TEXT('\0');
1741 memset (&sfn
, 0x00, sizeof(sfn
));
1742 sfn
.lStructSize
= sizeof(sfn
);
1743 sfn
.hwndOwner
= hParent
;
1744 sfn
.hInstance
= THIS_HINST
;
1745 sfn
.lpstrFilter
= szFilter
;
1746 sfn
.nFilterIndex
= 1;
1747 sfn
.lpstrFile
= pszFilename
;
1748 sfn
.nMaxFile
= MAX_PATH
;
1749 sfn
.Flags
= OFN_HIDEREADONLY
| OFN_NOREADONLYRETURN
| OFN_PATHMUSTEXIST
| OFN_OVERWRITEPROMPT
;
1750 sfn
.lCustData
= lCustData
;
1752 if (iddTemplate
!= 0)
1754 sfn
.lpTemplateName
= MAKEINTRESOURCE( iddTemplate
);
1755 sfn
.Flags
|= OFN_ENABLETEMPLATE
| OFN_EXPLORER
;
1757 if (lpfnHook
!= NULL
)
1759 sfn
.lpfnHook
= lpfnHook
;
1760 sfn
.Flags
|= OFN_ENABLEHOOK
| OFN_EXPLORER
;
1763 TCHAR szPath
[ MAX_PATH
];
1764 GetCurrentDirectory (MAX_PATH
, szPath
);
1765 if (pszLastDirectory
&& *pszLastDirectory
)
1766 SetCurrentDirectory (pszLastDirectory
);
1768 BOOL rc
= GetSaveFileName (&sfn
);
1770 if (pszLastDirectory
)
1771 GetCurrentDirectory (MAX_PATH
, pszLastDirectory
);
1772 SetCurrentDirectory (szPath
);
1779 * HOURGLASS CURSOR ETC _______________________________________________________
1783 static LONG nHourGlassRequests
= 0;
1785 void StartHourGlass (void)
1787 if ((++nHourGlassRequests
) == 1)
1789 SetCursor (LoadCursor (NULL
, IDC_WAIT
));
1793 void StopHourGlass (void)
1795 if ((nHourGlassRequests
== 0) || ((--nHourGlassRequests
) == 0))
1797 SetCursor (LoadCursor (NULL
, IDC_ARROW
));
1803 void DisplayContextMenu (HMENU hm
, POINT ptScreen
, HWND hParent
)
1805 HMENU hmDummy
= CreateMenu();
1806 InsertMenu (hmDummy
, 0, MF_POPUP
, (UINT
)(UINT_PTR
)hm
, NULL
);
1808 TrackPopupMenu (GetSubMenu (hmDummy
, 0),
1809 TPM_LEFTALIGN
| TPM_RIGHTBUTTON
,
1810 ptScreen
.x
, ptScreen
.y
,
1813 DestroyMenu (hmDummy
);
1817 size_t CountChildren (HWND hParent
, LPTSTR pszClass
)
1821 for (HWND hChild
= GetWindow (hParent
, GW_CHILD
);
1823 hChild
= GetWindow (hChild
, GW_HWNDNEXT
))
1825 TCHAR szClassName
[ cchRESOURCE
];
1827 if (GetClassName (hChild
, szClassName
, cchRESOURCE
))
1829 if (!lstrcmp (szClassName
, pszClass
))
1838 WORD
NextControlID (HWND hParent
)
1842 for (HWND hChild
= GetWindow (hParent
, GW_CHILD
);
1844 hChild
= GetWindow (hChild
, GW_HWNDNEXT
))
1846 LONG wChild
= GetWindowLong (hChild
, GWL_ID
);
1847 if ((wChild
< 0) || (wChild
>= 0xF000))
1850 wNext
= max( wNext
, (WORD
) wChild
+1 );
1857 BOOL
IsAncestor (HWND hParent
, HWND hChild
)
1859 for ( ; hChild
; hChild
= GetParent(hChild
))
1861 if (hParent
== hChild
)
1868 HWND
GetTabChild (HWND hTab
)
1870 for (HWND hChild
= GetWindow (hTab
, GW_CHILD
);
1872 hChild
= GetWindow (hChild
, GW_HWNDNEXT
))
1874 TCHAR szClassName
[ cchRESOURCE
];
1876 if (GetClassName (hChild
, szClassName
, cchRESOURCE
))
1878 if (!lstrcmp (szClassName
, TEXT("#32770"))) // WC_DIALOG
1887 HWND
GetLastDlgTabItem (HWND hDlg
)
1892 for (HWND hSearch
= GetNextDlgTabItem (hDlg
, NULL
, FALSE
);
1893 (hSearch
!= NULL
) && (hSearch
!= hFirst
);
1894 hSearch
= GetNextDlgTabItem (hDlg
, hSearch
, FALSE
))
1905 BOOL
IsPropSheet (HWND hSheet
)
1908 if ((hTab
= GetDlgItem (hSheet
, IDC_PROPSHEET_TABCTRL
)) == NULL
)
1911 TCHAR szClassName
[ cchRESOURCE
];
1912 if (!GetClassName (hTab
, szClassName
, cchRESOURCE
))
1915 if (lstrcmp (szClassName
, WC_TABCONTROL
))