⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wtl for mfc programmers, part viii.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:
ever</H3>
      <P>After making an SDI project with the WTL AppWizard, we can =
start by=20
      creating a sheet to use for our About box. Let's start with the =
about=20
      dialog the wizard creates for us, and change the styles so it will =
work as=20
      a property page.</P>
      <P>The first step is to remove the OK button, since that doesn't =
make=20
      sense in a sheet. On the <I>Styles</I> tab, change the =
<I>Style</I> to=20
      <I>Child</I>, and the <I>Border</I> to <I>Thin</I>, while leaving =
<I>Title=20
      bar</I> checked. On the <I>More Styles</I> tab, check =
<I>Disabled</I>.</P>
      <P>The second (and final) step is to create a property sheet in =
the=20
      <CODE>OnAppAbout()</CODE> handler. We can do this with the=20
      non-customizable <CODE>CPropertySheet</CODE> and=20
      <CODE>CPropertyPage</CODE> classes:</P><PRE>LRESULT =
CMainFrame::OnAppAbout(...)
{
CPropertySheet sheet ( _T(<SPAN class=3Dcpp-string>"About =
PSheets"</SPAN>) );
CPropertyPage&lt;IDD_ABOUTBOX&gt; pgAbout;
=20
    sheet.AddPage ( pgAbout );
    sheet.DoModal();
    <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}</PRE>
      <P>The result looks like this:</P>
      <P><IMG height=3D282 alt=3D" [Simple sheet - 5K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC8/simplesheet.png" =
width=3D344=20
      align=3Dbottom border=3D0></P>
      <H3><A name=3Dusefulpage></A>Creating a useful property page</H3>
      <P>Since not every page in every sheet is as simple as an About =
box, most=20
      pages will require a <CODE>CPropertyPageImpl</CODE>-derived class, =
so=20
      we'll take a look at such a class now. We'll make a new property =
page that=20
      contains the settings for the graphics shown in the background of =
the=20
      client area. Here's the dialog:</P>
      <P><IMG height=3D190 alt=3D" [Background options - 4K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC8/bkgndsheet.png" =
width=3D243=20
      align=3Dbottom border=3D0></P>
      <P>This dialog has the same styles as the About page. We'll need a =
new=20
      class to go along with the page, called =
<CODE>CBackgroundOptsPage</CODE>.=20
      This class derives from <CODE>CPropertyPageImpl</CODE> since it's =
a=20
      property page, and <CODE>CWinDataExchange</CODE> to enable =
DDX.</P><PRE><SPAN class=3Dcpp-keyword>class</SPAN> CBackgroundOptsPage =
:
    <SPAN class=3Dcpp-keyword>public</SPAN> =
CPropertyPageImpl&lt;CBackgroundOptsPage&gt;,
    <SPAN class=3Dcpp-keyword>public</SPAN> =
CWinDataExchange&lt;CBackgroundOptsPage&gt;
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
    <SPAN class=3Dcpp-keyword>enum</SPAN> { IDD =3D IDD_BACKGROUND_OPTS =
};
=20
    <SPAN class=3Dcpp-comment>// Construction</SPAN>
    CBackgroundOptsPage();
    ~CBackgroundOptsPage();
=20
    <SPAN class=3Dcpp-comment>// Maps</SPAN>
    BEGIN_MSG_MAP(CBackgroundOptsPage)
        MSG_WM_INITDIALOG(OnInitDialog)
        CHAIN_MSG_MAP(CPropertyPageImpl&lt;CBackgroundOptsPage&gt;)
    END_MSG_MAP()
=20
    BEGIN_DDX_MAP(CBackgroundOptsPage)
        DDX_RADIO(IDC_BLUE, m_nColor)
        DDX_RADIO(IDC_ALYSON, m_nPicture)
    END_DDX_MAP()
=20
    <SPAN class=3Dcpp-comment>// Message handlers</SPAN>
    BOOL OnInitDialog ( HWND hwndFocus, LPARAM lParam );
=20
    <SPAN class=3Dcpp-comment>// Property page notification =
handlers</SPAN>
    <SPAN class=3Dcpp-keyword>int</SPAN> OnApply();
=20
    <SPAN class=3Dcpp-comment>// DDX variables</SPAN>
    <SPAN class=3Dcpp-keyword>int</SPAN> m_nColor, m_nPicture;
};</PRE>
      <P>Things to note in this class:=20
      <UL>
        <LI>There is a public member named <CODE>IDD</CODE> that holds =
the=20
        associated dialog resource ID.=20
        <LI>The message map resembles that of a <CODE>CDialogImpl</CODE> =
class.=20
        <LI>The message map chains messages to =
<CODE>CPropertyPageImpl</CODE> so=20
        that property sheet-related notification messages are handled.=20
        <LI>There is an <CODE>OnApply()</CODE> handler to save the =
user's=20
        choices when he clicks OK in the sheet. </LI></UL>
      <P><CODE>OnApply()</CODE> is pretty simple, it calls=20
      <CODE>DoDataExchange()</CODE> to update the DDX variables, then =
returns a=20
      code indicating whether the sheet should close or =
not:</P><PRE><SPAN class=3Dcpp-keyword>int</SPAN> =
CBackgroundOptsPage::OnApply()
{
    <SPAN class=3Dcpp-keyword>return</SPAN> DoDataExchange(<SPAN =
class=3Dcpp-keyword>true</SPAN>) ? PSNRET_NOERROR : PSNRET_INVALID;
}</PRE>
      <P>In the main frame, we'll add a <I>Tools|Options</I> menu item =
that=20
      brings up the property sheet. The handler for this command creates =
the=20
      property sheet as before, but with the new=20
      <CODE>CBackgroundOptsPage</CODE> added to the sheet.</P><PRE><SPAN =
class=3Dcpp-keyword>void</SPAN> CMainFrame::OnOptions ( UINT uCode, =
<SPAN class=3Dcpp-keyword>int</SPAN> nID, HWND hwndCtrl )
{
CPropertySheet sheet ( _T(<SPAN class=3Dcpp-string>"PSheets =
Options"</SPAN>), <SPAN class=3Dcpp-literal>0</SPAN> );
CBackgroundOptsPage pgBackground;
CPropertyPage&lt;IDD_ABOUTBOX&gt; pgAbout;
=20
    pgBackground.m_nColor =3D m_view.m_nColor;
    pgBackground.m_nPicture =3D m_view.m_nPicture;
=20
    sheet.m_psh.dwFlags |=3D PSH_NOAPPLYNOW;
=20
    sheet.AddPage ( pgBackground );
    sheet.AddPage ( pgAbout );
=20
    <SPAN class=3Dcpp-keyword>if</SPAN> ( IDOK =3D=3D sheet.DoModal() )
        m_view.SetBackgroundOptions ( pgBackground.m_nColor,
                                      pgBackground.m_nPicture );
}</PRE>
      <P>The <CODE>sheet</CODE> constructor now has a second parameter =
of 0,=20
      meaning that the page at index 0 should be visible initially. You =
could=20
      change that to 1 to have the About page be visible when the sheet =
first=20
      appears. Since this is just demo code, I'm going to be lazy and =
make the=20
      <CODE>CBackgroundOptsPage</CODE> variables connected to the radio =
buttons=20
      public. The main frame will just store the initial values in those =

      variables, and read them again if the user clicks OK in the =
sheet.</P>
      <P>If the user clicks OK, <CODE>DoModal()</CODE> returns=20
      <CODE>IDOK</CODE>, and we tell the view the new picture and color =
to use.=20
      Here are some screen shots to show the different views:</P>
      <P><A =
href=3D"http://www.codeproject.com/wtl/WTL4MFC8/app_aly.jpg"><IMG=20
      height=3D152 alt=3D" [Alyson background - 11K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC8/app_aly_t.png" =
width=3D131=20
      align=3Dbottom border=3D2></A> <A=20
      href=3D"http://www.codeproject.com/wtl/WTL4MFC8/sb_app.png"><IMG =
height=3D133=20
      alt=3D" [Strong Bad background - 9K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC8/sb_app_t.png" =
width=3D95=20
      align=3Dbottom border=3D2></A></P>
      <H3><A name=3Dbettersheet></A>Creating a better property sheet =
class</H3>
      <P>The <CODE>OnOptions()</CODE> handler creates the sheet just =
fine, but=20
      there's an awful lot of setup and initialization code there, which =
really=20
      shouldn't be <CODE>CMainFrame</CODE>'s responsibility. A better =
way is to=20
      make a class derived from <CODE>CPropertySheetImpl</CODE> that =
handles=20
      those tasks.</P><PRE><SPAN class=3Dcpp-preprocessor>#include =
"BackgroundOptsPage.h"</SPAN>
=20
<SPAN class=3Dcpp-keyword>class</SPAN> CAppPropertySheet : <SPAN =
class=3Dcpp-keyword>public</SPAN> =
CPropertySheetImpl&lt;CAppPropertySheet&gt;
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
    <SPAN class=3Dcpp-comment>// Construction</SPAN>
    CAppPropertySheet ( _U_STRINGorID title =3D (LPCTSTR) NULL,=20
                        UINT uStartPage =3D <SPAN =
class=3Dcpp-literal>0</SPAN>, HWND hWndParent =3D NULL );

    <SPAN class=3Dcpp-comment>// Maps</SPAN>
    BEGIN_MSG_MAP(CAppPropertySheet)
        CHAIN_MSG_MAP(CPropertySheetImpl&lt;CAppPropertySheet&gt;)
    END_MSG_MAP()

    <SPAN class=3Dcpp-comment>// Property pages</SPAN>
    CBackgroundOptsPage         m_pgBackground;
    CPropertyPage&lt;IDD_ABOUTBOX&gt; m_pgAbout;
};</PRE>
      <P>With this class, we've encapsulated the details of what pages =
are in=20
      the sheet, and moved them into the sheet class itself. The =
constructor=20
      handles adding the pages to the sheet, and setting any other =
necessary=20
      flags:</P><PRE>CAppPropertySheet::CAppPropertySheet ( =
_U_STRINGorID title, UINT uStartPage,=20
                                       HWND hWndParent ) :
    CPropertySheetImpl&lt;CAppPropertySheet&gt; ( title, uStartPage, =
hWndParent )
{
    m_psh.dwFlags |=3D PSH_NOAPPLYNOW;

    AddPage ( m_pgBackground );
    AddPage ( m_pgAbout );
}</PRE>
      <P>As a result, the <CODE>OnOptions()</CODE> handler becomes a bit =

      simpler:</P><PRE><SPAN class=3Dcpp-keyword>void</SPAN> =
CMainFrame::OnOptions ( UINT uCode, <SPAN class=3Dcpp-keyword>int</SPAN> =
nID, HWND hwndCtrl )
{
CAppPropertySheet sheet ( _T(<SPAN class=3Dcpp-string>"PSheets =
Options"</SPAN>), <SPAN class=3Dcpp-literal>0</SPAN> );

    sheet.m_pgBackground.m_nColor =3D m_view.m_nColor;
    sheet.m_pgBackground.m_nPicture =3D m_view.m_nPicture;

    <SPAN class=3Dcpp-keyword>if</SPAN> ( IDOK =3D=3D sheet.DoModal() )
        m_view.SetBackgroundOptions ( sheet.m_pgBackground.m_nColor,
                                      sheet.m_pgBackground.m_nPicture );
}</PRE>
      <H2><A name=3Dcreatewiz></A>Creating a Wizard</H2>
      <P>Creating a wizard is, not surprisingly, similar to creating a =
property=20
      sheet. A little more work is required to enable the <I>Back</I> =
and=20
      <I>Next</I> buttons; just as in MFC property pages, you override=20
      <CODE>OnSetActive()</CODE> and call =
<CODE>SetWizardButtons()</CODE> to=20
      enable the appropriate buttons. We'll start with a simple =
introduction=20
      page, with ID <CODE>IDD_WIZARD_INTRO</CODE>:</P>
      <P><IMG height=3D307 alt=3D" [Intro page - 3K] "=20
      src=3D"http://www.codeproject.com/wtl/WTL4MFC8/intropage.png" =
width=3D351=20
      align=3Dbottom border=3D0></P>
      <P>Notice that the page has no caption text. Since every page in a =
wizard=20
      usually has the same title, I prefer to set the text in the=20
      CPropertySheetImpl constructor, and have every page use the same =
string=20
      resource. That way, I can just change that one string and every =
page will=20
      reflect the change.</P>
      <P>The implementation of this page is done in the=20
      <CODE>CWizIntroPage</CODE> class:</P><PRE><SPAN =
class=3Dcpp-keyword>class</SPAN> CWizIntroPage : <SPAN =
class=3Dcpp-keyword>public</SPAN> CPropertyPageImpl&lt;CWizIntroPage&gt;
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
    <SPAN class=3Dcpp-keyword>enum</SPAN> { IDD =3D IDD_WIZARD_INTRO };

    <SPAN class=3Dcpp-comment>// Construction</SPAN>
    CWizIntroPage();

    <SPAN class=3Dcpp-comment>// Maps</SPAN>
    BEGIN_MSG_MAP(COptionsWizard)
        CHAIN_MSG_MAP(CPropertyPageImpl&lt;CWizIntroPage&gt;)
    END_MSG_MAP()

    <SPAN class=3Dcpp-comment>// Notification handlers</SPAN>
    <SPAN class=3Dcpp-keyword>int</SPAN> OnSetActive();
};</PRE>
      <P>The constructor sets the page's text by referencing a string =
resource=20
      ID:</P><PRE>CWizIntroPage::CWizIntroPage() :
    CPropertyPageImpl&lt;CWizIntroPage&gt;( IDS_WIZARD_TITLE )
{
}</PRE>
      <P>The string <CODE>IDS_WIZARD_TITLE</CODE> ("PSheets Options =
Wizard")=20
      will appear in the wizard's caption bar when this page is the =
current=20
      page. <CODE>OnSetActive()</CODE> enables just the <I>Next</I> =
button:</P><PRE><SPAN class=3Dcpp-keyword>int</SPAN> =
CWizIntroPage::OnSetActive()
{
    SetWizardButtons ( PSWIZB_NEXT );
    <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}</PRE>
      <P>To implement the wizard, we'll create a class=20
      <CODE>COptionsWizard</CODE>, and a <I>Tools</I>|<I>Wizard</I> menu =
option=20
      in the main frame's menu. The <CODE>COptionsWizard</CODE> =
constructor is=20
      pretty similar to <CODE>CAppPropertySheet</CODE>'s, in that it =
sets any=20
      necessary style bits or flags, and adds pages to the =
sheet.</P><PRE><SPAN class=3Dcpp-keyword>class</SPAN> COptionsWizard : =
<SPAN class=3Dcpp-keyword>public</SPAN> =
CPropertySheetImpl&lt;COptionsWizard&gt;
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
    <SPAN class=3Dcpp-comment>// Construction</SPAN>
    COptionsWizard ( HWND hWndParent =3D NULL );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -