📄 wtl for mfc programmers, part viii.mht
字号:
<CODE>CPropertySheetImpl</CODE>. Since many methods are just =
wrappers=20
around window messages, I won't present an exhaustive list here, =
but you=20
can check out atldlgs.h to see the complete list of =
methods.</P><PRE>CPropertySheetImpl(_U_STRINGorID title =3D (LPCTSTR) =
NULL,
UINT uStartPage =3D <SPAN =
class=3Dcpp-literal>0</SPAN>, HWND hWndParent =3D NULL)</PRE>
<P>The <CODE>CPropertySheetImpl</CODE> constructor lets you =
specify some=20
common properties right away, so you don't have to call other =
methods=20
later to set them. <CODE>title</CODE> specifies the text to use in =
the=20
property sheet's caption. <CODE>_U_STRINGorID</CODE> is a WTL =
utility=20
class that lets you pass either an <CODE>LPCTSTR</CODE> or string =
resource=20
ID. For example, both of these lines will work:</P><PRE> =
CPropertySheetImpl mySheet ( IDS_SHEET_TITLE );
CPropertySheetImpl mySheet ( _T(<SPAN class=3Dcpp-string>"My prop =
sheet"</SPAN>) );</PRE>
<P>if <CODE>IDS_SHEET_TITLE</CODE> is the ID of a string in the =
string=20
table. <CODE>uStartPage</CODE> is the zero-based index of the page =
that=20
should be active when the sheet is first made visible.=20
<CODE>hWndParent</CODE> sets the sheet's parent =
window.</P><PRE>BOOL AddPage(HPROPSHEETPAGE hPage)
BOOL AddPage(LPCPROPSHEETPAGE pPage)</PRE>
<P>Adds a property page to the sheet. If the page is already =
created, you=20
can pass its handle (an <CODE>HPROPSHEETPAGE</CODE>) to the first=20
overload. The more common way is to use the second overload. With =
that=20
version, you set up a <CODE>PROPSHEETPAGE</CODE> struct (which you =
can do=20
with <CODE>CPropertyPageImpl</CODE>, covered later) and=20
<CODE>CPropertySheetImpl</CODE> will create and manage the page =
for=20
you.</P><PRE>BOOL RemovePage(HPROPSHEETPAGE hPage)
BOOL RemovePage(<SPAN class=3Dcpp-keyword>int</SPAN> nPageIndex)</PRE>
<P>Removes a page from the sheet. You can pass either the page's =
handle or=20
its zero-based index.</P><PRE>BOOL SetActivePage(HPROPSHEETPAGE =
hPage)
BOOL SetActivePage(<SPAN class=3Dcpp-keyword>int</SPAN> =
nPageIndex)</PRE>
<P>Sets the active page in the sheet. You can pass either the =
handle or=20
zero-based index of the page to be made active. You can call this =
method=20
before creating the property sheet to set which page will be =
active when=20
the sheet is first made visible.</P><PRE><SPAN =
class=3Dcpp-keyword>void</SPAN> SetTitle(LPCTSTR lpszText, UINT nStyle =
=3D <SPAN class=3Dcpp-literal>0</SPAN>)</PRE>
<P>Sets the text to be used in the caption of the property sheet. =
nStyle=20
can be either 0 or <CODE>PSH_PROPTITLE</CODE>. If it is=20
<CODE>PSH_PROPTITLE</CODE>, then that style bit is added to the =
sheet,=20
which causes the words "Properties for" to be prepended to the =
text you=20
pass in <CODE>lpszText</CODE>.</P><PRE><SPAN =
class=3Dcpp-keyword>void</SPAN> SetWizardMode()</PRE>
<P>Sets the <CODE>PSH_WIZARD</CODE> style, which changes the sheet =
into a=20
wizard. You must call this method before showing the =
sheet.</P><PRE><SPAN class=3Dcpp-keyword>void</SPAN> EnableHelp()</PRE>
<P>Sets the <CODE>PSH_HASHELP</CODE> style, which adds a Help =
button to=20
the sheet. Note that you also need to enable help in each page =
that=20
provides help for this to take effect.</P><PRE>INT_PTR =
DoModal(HWND hWndParent =3D ::GetActiveWindow())</PRE>
<P>Creates and shows a modal property sheet. The return value is =
positive=20
to indicate success, see the docs on the =
<CODE>PropertySheet()</CODE> API=20
for a full description of the return value. If an error occurs and =
the=20
sheet can't be created, <CODE>DoModal()</CODE> returns =
-1.</P><PRE>HWND Create(HWND hWndParent =3D NULL)</PRE>
<P>Creates and shows a modeless property sheet, and returns its =
window=20
handle. If an error occurs and the sheet can't be created,=20
<CODE>Create()</CODE> returns NULL.</P>
<H2><A name=3Dpageclasses></A>WTL Property Page Classes</H2>
<P>The WTL classes that encapsulate property pages work similarly =
to the=20
property sheet classes. There is a window interface class,=20
<CODE>CPropertyPageWindow</CODE>, and an implementation class,=20
<CODE>CPropertyPageImpl</CODE>. <CODE>CPropertyPageWindow</CODE> =
is very=20
small, and contains mostly utility functions that call methods in =
the=20
parent sheet.</P>
<P><CODE>CPropertyPageImpl</CODE> derives from=20
<CODE>CDialogImplBaseT</CODE>, since a page is built from a dialog =
resource. That means that all the WTL features we've used in =
dialogs are=20
also available in property sheets, like DDX and DDV.=20
<CODE>CPropertyPageImpl</CODE> has two main purposes: it manages a =
<CODE>PROPSHEETPAGE</CODE> struct (kept in the member variable=20
<CODE>m_psp</CODE>), and handles <CODE>PSN_*</CODE> notification =
messages.=20
For very simple property pages, you can use the =
<CODE>CPropertyPage</CODE>=20
class. This is only suitable for pages that do not interact with =
the user=20
at all, for example an About page, or the introduction page in a=20
wizard.</P>
<P>You can also create pages that host ActiveX controls. You first =
include=20
atlhost.h in stdafx.h. For the page, you use=20
<CODE>CAxPropertyPageImpl</CODE> instead of=20
<CODE>CPropertyPageImpl</CODE>. For simple pages that host ActiveX =
controls, you can use <CODE>CAxPropertyPage</CODE> instead of=20
<CODE>CPropertyPage</CODE>.</P>
<H3><A name=3Dpagewinmethods></A>CPropertyPageWindow methods</H3>
<P><CODE>CPropertyPageWindow</CODE>'s most important method is=20
<CODE>GetPropertySheet()</CODE>:</P><PRE>CPropertySheetWindow =
GetPropertySheet()</PRE>
<P>This method gets the <CODE>HWND</CODE> of the page's parent =
window (the=20
sheet) and attaches a <CODE>CPropertySheetWindow</CODE> to that=20
<CODE>HWND</CODE>. The new <CODE>CPropertySheetWindow</CODE> is =
then=20
returned to the caller. Note that this only creates a temporary =
object; it=20
does <B>not</B> return a pointer or reference to the actual=20
<CODE>CPropertySheet</CODE> or <CODE>CPropertySheetImpl</CODE> =
object used=20
to create the sheet. This is important if you are using your own=20
<CODE>CPropertySheetImpl</CODE>-derived class and need to access =
data=20
members in the sheet object.</P>
<P>The remaining members just call through to=20
<CODE>CPropertySheetWindow</CODE> functions that wrap =
<CODE>PSM_*</CODE>=20
messages:</P><PRE>BOOL Apply()
<SPAN class=3Dcpp-keyword>void</SPAN> CancelToClose()
<SPAN class=3Dcpp-keyword>void</SPAN> SetModified(BOOL bChanged =3D =
TRUE)
LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
<SPAN class=3Dcpp-keyword>void</SPAN> RebootSystem()
<SPAN class=3Dcpp-keyword>void</SPAN> RestartWindows()
<SPAN class=3Dcpp-keyword>void</SPAN> SetWizardButtons(DWORD =
dwFlags)</PRE>
<P>For example, in a <CODE>CPropertyPageImpl</CODE>-derived class, =
you can=20
call:</P><PRE> SetWizardButtons ( PSWIZB_BACK | PSWIZB_FINISH =
);</PRE>
<P>instead of:</P><PRE>CPropertySheetWindow wndSheet;
=20
wndSheet =3D GetPropertySheet();
wndSheet.SetWizardButtons ( PSWIZB_BACK | PSWIZB_FINISH );</PRE>
<H3><A name=3Dpageimplmethods></A>CPropertyPageImpl methods</H3>
<P><CODE>CPropertyPageImpl</CODE> manages a =
<CODE>PROPSHEETPAGE</CODE>=20
struct, the public member <CODE>m_psp</CODE>.=20
<CODE>CPropertyPageImpl</CODE> also has an <CODE><SPAN=20
class=3Dcpp-keyword>operator</SPAN> PROPSHEETPAGE*</CODE> =
converter, so you=20
can pass a <CODE>CPropertyPageImpl</CODE> to a method that takes =
an=20
<CODE>LPPROPSHEETPAGE</CODE> or <CODE>LPCPROPSHEETPAGE</CODE>, =
such as=20
<CODE>CPropertySheetImpl::AddPage()</CODE>.</P>
<P>The <CODE>CPropertyPageImpl</CODE> constructor lets you set the =
page=20
title, which is the text that appears on the page's =
tab:</P><PRE>CPropertyPageImpl(_U_STRINGorID title =3D (LPCTSTR) =
NULL)</PRE>
<P>If you ever need to create a page manually, instead of letting =
the=20
sheet do it, you can call =
<CODE>Create()</CODE>:</P><PRE>HPROPSHEETPAGE Create()</PRE>
<P><CODE>Create()</CODE> just calls =
<CODE>CreatePropertySheetPage()</CODE>=20
with <CODE>m_psp</CODE> as the parameter. You would only need to =
call=20
<CODE>Create()</CODE> if you are adding pages to a sheet after the =
sheet=20
is created, or if you are creating a page to be passed to some =
other sheet=20
not under your control (for example, a <A=20
=
href=3D"http://www.codeproject.com/shell/ShellExtGuide5.asp">property =
sheet=20
handler shell extension</A>).</P>
<P>There are three methods for setting various title text on the =
page:</P><PRE><SPAN class=3Dcpp-keyword>void</SPAN> =
SetTitle(_U_STRINGorID title)
<SPAN class=3Dcpp-keyword>void</SPAN> SetHeaderTitle(LPCTSTR =
lpstrHeaderTitle)
<SPAN class=3Dcpp-keyword>void</SPAN> SetHeaderSubTitle(LPCTSTR =
lpstrHeaderSubTitle)</PRE>
<P>The first changes the text on the page's tab. The other two are =
used in=20
Wizard97-style wizards to set the text in the header above the =
property=20
page area.</P><PRE><SPAN class=3Dcpp-keyword>void</SPAN> =
EnableHelp()</PRE>
<P>Sets the <CODE>PSP_HASHELP</CODE> flag in <CODE>m_psp</CODE> to =
enable=20
the Help button when the page is active.</P>
<H3><A name=3Dhandlingnotify></A>Handling notification =
messages</H3>
<P><CODE>CPropertyPageImpl</CODE> has a message map that handles=20
<CODE>WM_NOTIFY</CODE>. If the notification code is a =
<CODE>PSN_*</CODE>=20
value, <CODE>OnNotify()</CODE> calls a handler for that particular =
notification. This is done using the compile-time virtual function =
technique, so the handlers can be easily overridden in derived=20
classes.</P>
<P>There are two sets of notification handlers, due to a design =
change=20
between WTL 3 and 7. In WTL 3, the notification handlers had =
return values=20
that differ from the return values for the <CODE>PSN_*</CODE> =
messages.=20
For example, the WTL 3 handler for <CODE>PSN_WIZFINISH</CODE> =
is:</P><PRE> <SPAN class=3Dcpp-keyword>case</SPAN> PSN_WIZFINISH:
lResult =3D !pT->OnWizardFinish();
<SPAN class=3Dcpp-keyword>break</SPAN>;</PRE>
<P><CODE>OnWizardFinish()</CODE> was expected to return =
<CODE>TRUE</CODE>=20
to let the wizard finish, or <CODE>FALSE</CODE> to prevent the =
wizard from=20
closing. This broke, however, when the IE 5 common controls added =
the=20
ability to return a window handle from the =
<CODE>PSN_WIZFINISH</CODE>=20
handler to give that window the focus. WTL 3 apps could not use =
this=20
feature because all non-zero values were treated the same.</P>
<P>In WTL 7, <CODE>OnNotify()</CODE> does not change any value =
returned=20
from a <CODE>PSN_*</CODE> handler. The handlers can return any =
documented=20
legal value and the behavior will be correct. However, for =
backwards=20
compatibility, the WTL 3 handlers are still present and are used =
by=20
default. To use the WTL 7 handlers, you must add this line to =
stdafx.h=20
before including atldlgs.h:</P><PRE><SPAN =
class=3Dcpp-preprocessor>#define =
_WTL_NEW_PAGE_NOTIFY_HANDLERS</SPAN></PRE>
<P>When writing new code, there is no reason not to use the WTL 7=20
handlers, so the WTL 3 handlers will not be covered here.</P>
<P><CODE>CPropertyPageImpl</CODE> has default handlers for all=20
notifications, so you can override only the handlers that are =
relevant to=20
your program. The default handlers and their actions are:</P>
<BLOCKQUOTE>
<P><CODE><SPAN class=3Dcpp-keyword>int</SPAN> =
OnSetActive()</CODE> -=20
allows the page to become active</P>
<P><CODE>BOOL OnKillActive()</CODE> - allows the page to become=20
inactive</P>
<P><CODE><SPAN class=3Dcpp-keyword>int</SPAN> OnApply()</CODE> - =
returns=20
<CODE>PSNRET_NOERROR</CODE> to indicate the apply operation=20
succeeded</P>
<P><CODE><SPAN class=3Dcpp-keyword>void</SPAN> OnReset()</CODE> =
- no=20
action</P>
<P><CODE>BOOL OnQueryCancel()</CODE> - allows the cancel =
operation</P>
<P><CODE><SPAN class=3Dcpp-keyword>int</SPAN> =
OnWizardBack()</CODE> - goes=20
to the previous page</P>
<P><CODE><SPAN class=3Dcpp-keyword>int</SPAN> =
OnWizardNext()</CODE> - goes=20
to the next page</P>
<P><CODE>INT_PTR OnWizardFinish()</CODE> - allows the wizard to=20
finish</P>
<P><CODE><SPAN class=3Dcpp-keyword>void</SPAN> OnHelp()</CODE> - =
no=20
action</P>
<P><CODE>BOOL OnGetObject(LPNMOBJECTNOTIFY =
lpObjectNotify)</CODE> - no=20
action</P>
<P><CODE><SPAN class=3Dcpp-keyword>int</SPAN> =
OnTranslateAccelerator(LPMSG=20
lpMsg)</CODE> - returns <CODE>PSNRET_NOERROR</CODE> to indicate =
that the=20
message was not handled</P>
<P><CODE>HWND OnQueryInitialFocus(HWND hWndFocus)</CODE> - =
returns NULL=20
to set the focus to the first control in the tab =
order</P></BLOCKQUOTE>
<H2><A name=3Dcreatingsheet></A>Creating a Property Sheet</H2>
<P>Now that our tour of the classes is complete, we need a program =
to=20
illustrate how to use them. The sample project for this article is =
a=20
simple SDI app that shows a picture in the client area, and fills =
the=20
background with a color. The picture and color can be changed via =
an=20
options dialog (a property sheet), and a wizard (which I'll =
describe=20
later).</P>
<H3><A name=3Dsimplesheet></A>The simplest property sheet, =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -