Overview

We have seen example of CPropertySheet and CPropertyPage class in our previous topic. However that was high level object oriented approach to implement a property sheet project. MFC OOP makes easy to implement these but the abstruction always hides the lower mechanism.

Here we are going to explore the lower layer data structures behind those classes.

PropertySheet

PropertySheet() is the main function to create a the main Property Sheet dialog. Creates a property sheet and adds the pages defined in the specified property sheet header structure.

INT_PTR PropertySheet(
   LPCPROPSHEETHEADER lppsph
);

Parameters

  • lppsph -Pointer to a PROPSHEETHEADER structure that defines the frame and pages of a property sheet.

Return value

For modal property sheets, the return value is as follows:

  • >=1 Changes were saved by the user.
  • 0 No changes were saved by the user.
  • -1 An error occurred.

PROPSHEETHEADER

PROPSHEETHEADER is the main structure to pass to PropertySheet() function. This structure contains main dialog attributes like title, dialog precedure, number of property pages, default start page index and pointer to one or more property pages. Property page pointer sould point to an array of page objects which are the attributes of individual pages.

typedef struct {
  DWORD                dwSize;     /* Size of the struct */
  DWORD                dwFlags;    /* Flag for diff members */
  HWND                 hwndParent;  /* Parent of this property sheet */
  HINSTANCE            hInstance;   /* App instance handle */
  union {
    HICON  hIcon;               /* Icon handle */
    LPCSTR pszIcon;             /* Icon name */
  };
  LPCTSTR              pszCaption;  /* Dialog caption */
  UINT                 nPages;      /* Number of pages */
  union {
    UINT    nStartPage;              /* Index of start page */
    LPCTSTR pStartPage;              /* start page as string */
  };
  union {
    LPCPROPSHEETPAGE ppsp;           /* array of property page descriptors */
    HPROPSHEETPAGE   *phpage;        /* array of property page handles */
  };
  PFNPROPSHEETCALLBACK pfnCallback;   /* Callback function pointer */
#if (_WIN32_IE >= 0x0400)
  union {
    HBITMAP hbmWatermark;
    LPCTSTR pszbmWatermark;
  };
  HPALETTE             hplWatermark;
  union {
    HBITMAP hbmHeader;
    LPCSTR  pszbmHeader;
  };
#endif 
} PROPSHEETHEADER, *LPPROPSHEETHEADER;

PROPSHEETPAGE structure

PROPSHEETPAGE is the structure to hold the attributes of individual pages. This structure contains attributes like dialog resource, title string, icon, dialog precedure. Programmers should populate all the necessary fields of the property pages. Programmer should also provide an array of this page objects when constructing PROPSHEETHEADER object for calling PropertySheet().

typedef struct {
  DWORD           dwSize;       /* Size of the struct */
  DWORD           dwFlags;      /* Flag for diff members */
  HINSTANCE       hInstance;    /* App instance handle */
  union {
    LPCSTR         pszTemplate; /* Resource template name */
    LPCDLGTEMPLATE pResource;   /* User constructed Resource */
  };
  union {
    HICON  hIcon;               /* Icon handle */
    LPCSTR pszIcon;             /* Icon name */
  };
  LPCSTR          pszTitle;          /* Title string */
  DLGPROC         pfnDlgProc;        /* Dialog presedure */
  LPARAM          lParam;            /* Dialog LPARAM */
  LPFNPSPCALLBACK pfnCallback;       /* Callback function pointer */
  UINT            *pcRefParent;
#if (_WIN32_IE >= 0x0500)
  LPCTSTR         pszHeaderTitle;
  LPCTSTR         pszHeaderSubTitle;
#endif 
#if (_WIN32_WINNT >= 0x0501)
  HANDLE          hActCtx;
#endif 
} PROPSHEETPAGE, *LPPROPSHEETPAGE;

PropertySheetPage functions

Property page objects can be passed as array or as the handle. There are few Property page related APIs to create and delete handle to property page.

CreatePropertySheetPage function

Creates a new page handle for a property sheet from the object of type PROPSHEETPAGE.

Syntax

HPROPSHEETPAGE CreatePropertySheetPage(
   LPCPROPSHEETPAGE lppsp
);

Return

Handle to the property page. An array of property page handle can be attached to PROPSHEETHEADER for creation of property sheet.

DestroyPropertySheetPage function

Destroys a property sheet page object corresponding to the handle given as input. An application must call this function to free the resource pointed by the handle. This is needed when property sheet dialog is closed and propery page is no longer needed.

Syntax

BOOL DestroyPropertySheetPage(
   HPROPSHEETPAGE hPSPage
);

Source code

VOID DoPropertySheet(HWND hwndOwner)
{
    PROPSHEETPAGE psp[2];
    
    PROPSHEETHEADER psh;
    
    psp[0].dwSize      = sizeof(PROPSHEETPAGE);
    psp[0].dwFlags     = PSP_USEICONID | PSP_USETITLE;
    psp[0].hInstance   = g_hinst;
    psp[0].pszTemplate = MAKEINTRESOURCE(DLG_FONT);
    psp[0].pszIcon     = MAKEINTRESOURCE(IDI_FONT);
    psp[0].pfnDlgProc  = FontDialogProc;
    psp[0].pszTitle    = MAKEINTRESOURCE(IDS_FONT)
    psp[0].lParam      = 0;
    psp[0].pfnCallback = NULL;
  
  
    psp[1].dwSize      = sizeof(PROPSHEETPAGE);
    psp[1].dwFlags     = PSP_USEICONID | PSP_USETITLE;
    psp[1].hInstance   = g_hinst;
    psp[1].pszTemplate = MAKEINTRESOURCE(DLG_BORDER);
    psp[1].pszIcon     = MAKEINTRESOURCE(IDI_BORDER);
    psp[1].pfnDlgProc  = BorderDialogProc;
    psp[1].pszTitle    = MAKEINTRESOURCE(IDS_BORDER);
    psp[1].lParam      = 0;
    psp[1].pfnCallback = NULL;
    
    psh.dwSize      = sizeof(PROPSHEETHEADER);
    psh.dwFlags     = PSH_USEICONID | PSH_PROPSHEETPAGE;
    psh.hwndParent  = hwndOwner;
    psh.hInstance   = g_hinst;
    psh.pszIcon     = MAKEINTRESOURCE(IDI_CELL_PROPERTIES);
    psh.pszCaption  = (LPSTR) "Cell Properties";
    psh.nPages      = sizeof(psp) / sizeof(PROPSHEETPAGE);
    psh.nStartPage  = 0;
    psh.ppsp        = (LPCPROPSHEETPAGE) &psp;
    psh.pfnCallback = NULL;
    
    PropertySheet(&psh);
    
    return;
}

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

#