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

📄 propsheet.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Property Sheets
 *
 * Copyright 1998 Francis Beaudet
 * Copyright 1999 Thuy Nguyen
 * Copyright 2004 Maxime Bellenge
 * Copyright 2004 Filip Navara
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 * This code was audited for completeness against the documented features
 * of Comctl32.dll version 6.0 on Sep. 12, 2004, by Filip Navara.
 * 
 * Unless otherwise noted, we believe this code to be complete, as per
 * the specification mentioned above.
 * If you discover missing features, or bugs, please note them below.
 *
 * TODO:
 *   - Tab order
 *   - Wizard 97 header resizing
 *   - Enforcing of minimal wizard size
 *   - Messages:
 *     o PSM_INSERTPAGE
 *     o PSM_RECALCPAGESIZES
 *     o PSM_SETHEADERSUBTITLE
 *     o PSM_SETHEADERTITLE
 *     o WM_HELP
 *     o WM_CONTEXTMENU
 *   - Notifications:
 *     o PSN_GETOBJECT
 *     o PSN_QUERYINITIALFOCUS
 *     o PSN_TRANSLATEACCELERATOR
 *   - Styles:
 *     o PSH_RTLREADING
 *     o PSH_STRETCHWATERMARK
 *     o PSH_USEPAGELANG
 *     o PSH_USEPSTARTPAGE
 *   - Page styles:
 *     o PSP_USEFUSIONCONTEXT
 *     o PSP_USEREFPARENT
 */

#include <stdarg.h>
#include <string.h>

#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "commctrl.h"
#include "prsht.h"
#include "comctl32.h"
#include "uxtheme.h"

#include "wine/debug.h"
#include "wine/unicode.h"

/******************************************************************************
 * Data structures
 */
#include "pshpack2.h"

typedef struct
{
  WORD dlgVer;
  WORD signature;
  DWORD helpID;
  DWORD exStyle;
  DWORD style;
} MyDLGTEMPLATEEX;

typedef struct
{
  DWORD helpid;
  DWORD exStyle;
  DWORD style;
  short x;
  short y;
  short cx;
  short cy;
  DWORD id;
} MyDLGITEMTEMPLATEEX;
#include "poppack.h"

typedef struct tagPropPageInfo
{
  HPROPSHEETPAGE hpage; /* to keep track of pages not passed to PropertySheet */
  HWND hwndPage;
  BOOL isDirty;
  LPCWSTR pszText;
  BOOL hasHelp;
  BOOL useCallback;
  BOOL hasIcon;
} PropPageInfo;

typedef struct tagPropSheetInfo
{
  HWND hwnd;
  PROPSHEETHEADERW ppshheader;
  BOOL unicode;
  LPWSTR strPropertiesFor;
  int nPages;
  int active_page;
  BOOL isModeless;
  BOOL hasHelp;
  BOOL hasApply;
  BOOL hasFinish;
  BOOL useCallback;
  BOOL activeValid;
  PropPageInfo* proppage;
  HFONT hFont;
  HFONT hFontBold;
  int width;
  int height;
  HIMAGELIST hImageList;
  BOOL ended;
  INT result;
} PropSheetInfo;

typedef struct
{
  int x;
  int y;
} PADDING_INFO;

/******************************************************************************
 * Defines and global variables
 */

static const WCHAR PropSheetInfoStr[] =
    {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 };

#define PSP_INTERNAL_UNICODE 0x80000000

#define MAX_CAPTION_LENGTH 255
#define MAX_TABTEXT_LENGTH 255
#define MAX_BUTTONTEXT_LENGTH 64

#define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)

/* Wizard metrics specified in DLUs */
#define WIZARD_PADDING 7
#define WIZARD_HEADER_HEIGHT 36
                         	
/******************************************************************************
 * Prototypes
 */
static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg);
static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText);
static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg);
static BOOL PROPSHEET_SetCurSel(HWND hwndDlg,
                                int index,
                                int skipdir,
                                HPROPSHEETPAGE hpage);
static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo);
static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg, const PropSheetInfo* psInfo);
static BOOL PROPSHEET_DoCommand(HWND hwnd, WORD wID);

static INT_PTR CALLBACK
PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

WINE_DEFAULT_DEBUG_CHANNEL(propsheet);

#define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");}
/******************************************************************************
 *            PROPSHEET_UnImplementedFlags
 *
 * Document use of flags we don't implement yet.
 */
static VOID PROPSHEET_UnImplementedFlags(DWORD dwFlags)
{
    CHAR string[256];

    string[0] = '\0';

  /*
   * unhandled header flags:
   *  PSH_RTLREADING         0x00000800
   *  PSH_STRETCHWATERMARK   0x00040000
   *  PSH_USEPAGELANG        0x00200000
   */

    add_flag(PSH_RTLREADING);
    add_flag(PSH_STRETCHWATERMARK);
    add_flag(PSH_USEPAGELANG);
    if (string[0] != '\0')
	FIXME("%s\n", string);
}
#undef add_flag

/******************************************************************************
 *            PROPSHEET_GetPageRect
 *
 * Retrieve rect from tab control and map into the dialog for SetWindowPos
 */
static void PROPSHEET_GetPageRect(const PropSheetInfo * psInfo, HWND hwndDlg,
                                  RECT *rc, LPCPROPSHEETPAGEW ppshpage)
{
    if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) {     
        HWND hwndChild;
        RECT r;

        if (((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
             (psInfo->ppshheader.dwFlags & PSH_HEADER) &&
             !(ppshpage->dwFlags & PSP_HIDEHEADER)) ||
            (psInfo->ppshheader.dwFlags & PSH_WIZARD))
        {
            rc->left = rc->top = WIZARD_PADDING;
        }
        else
        {
            rc->left = rc->top = 0;
        }
        rc->right = psInfo->width - rc->left;
        rc->bottom = psInfo->height - rc->top;
        MapDialogRect(hwndDlg, rc);

        if ((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
            (psInfo->ppshheader.dwFlags & PSH_HEADER) &&
            !(ppshpage->dwFlags & PSP_HIDEHEADER))
        {
            hwndChild = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER);
            GetClientRect(hwndChild, &r);
            MapWindowPoints(hwndChild, hwndDlg, (LPPOINT) &r, 2);
            rc->top += r.bottom + 1;
        }
    } else {
        HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL);
        GetClientRect(hwndTabCtrl, rc);
        SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)rc);
        MapWindowPoints(hwndTabCtrl, hwndDlg, (LPPOINT)rc, 2);
    }
}

/******************************************************************************
 *            PROPSHEET_FindPageByResId
 *
 * Find page index corresponding to page resource id.
 */
static INT PROPSHEET_FindPageByResId(PropSheetInfo * psInfo, LRESULT resId)
{
   INT i;

   for (i = 0; i < psInfo->nPages; i++)
   {
      LPCPROPSHEETPAGEA lppsp = (LPCPROPSHEETPAGEA)psInfo->proppage[i].hpage;

      /* Fixme: if resource ID is a string shall we use strcmp ??? */
      if (lppsp->u.pszTemplate == (LPVOID)resId)
         break;
   }

   return i;
}

/******************************************************************************
 *            PROPSHEET_AtoW
 *
 * Convert ASCII to Unicode since all data is saved as Unicode.
 */
static void PROPSHEET_AtoW(LPCWSTR *tostr, LPCSTR frstr)
{
    INT len;

    TRACE("<%s>\n", frstr);
    len = MultiByteToWideChar(CP_ACP, 0, frstr, -1, 0, 0);
    *tostr = Alloc(len * sizeof(WCHAR));
    MultiByteToWideChar(CP_ACP, 0, frstr, -1, (LPWSTR)*tostr, len);
}

/******************************************************************************
 *            PROPSHEET_CollectSheetInfoA
 *
 * Collect relevant data.
 */
static BOOL PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh,
                                       PropSheetInfo * psInfo)
{
  DWORD dwSize = min(lppsh->dwSize,sizeof(PROPSHEETHEADERA));
  DWORD dwFlags = lppsh->dwFlags;

  psInfo->hasHelp = dwFlags & PSH_HASHELP;
  psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
  psInfo->hasFinish = dwFlags & PSH_WIZARDHASFINISH;
  psInfo->useCallback = (dwFlags & PSH_USECALLBACK )&& (lppsh->pfnCallback);
  psInfo->isModeless = dwFlags & PSH_MODELESS;

  memcpy(&psInfo->ppshheader,lppsh,dwSize);
  TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%d\ndwFlags\t\t%08x\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n",
	lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance,
	debugstr_a(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback);

  PROPSHEET_UnImplementedFlags(lppsh->dwFlags);

  if (lppsh->dwFlags & INTRNL_ANY_WIZARD)
     psInfo->ppshheader.pszCaption = NULL;
  else
  {
     if (HIWORD(lppsh->pszCaption))
     {
        int len = MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, NULL, 0);
        psInfo->ppshheader.pszCaption = Alloc( len*sizeof (WCHAR) );
        MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, (LPWSTR) psInfo->ppshheader.pszCaption, len);
     }
  }
  psInfo->nPages = lppsh->nPages;

  if (dwFlags & PSH_USEPSTARTPAGE)
  {
    TRACE("PSH_USEPSTARTPAGE is on\n");
    psInfo->active_page = 0;
  }
  else
    psInfo->active_page = lppsh->u2.nStartPage;

  if (psInfo->active_page < 0 || psInfo->active_page >= psInfo->nPages)
     psInfo->active_page = 0;

  psInfo->result = 0;
  psInfo->hImageList = 0;
  psInfo->activeValid = FALSE;

  return TRUE;
}

/******************************************************************************
 *            PROPSHEET_CollectSheetInfoW
 *
 * Collect relevant data.
 */
static BOOL PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh,
                                       PropSheetInfo * psInfo)
{
  DWORD dwSize = min(lppsh->dwSize,sizeof(PROPSHEETHEADERW));
  DWORD dwFlags = lppsh->dwFlags;

  psInfo->hasHelp = dwFlags & PSH_HASHELP;
  psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW);
  psInfo->hasFinish = dwFlags & PSH_WIZARDHASFINISH;
  psInfo->useCallback = (dwFlags & PSH_USECALLBACK) && (lppsh->pfnCallback);
  psInfo->isModeless = dwFlags & PSH_MODELESS;

  memcpy(&psInfo->ppshheader,lppsh,dwSize);
  TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%d\ndwFlags\t\t%08x\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n",
      lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance, debugstr_w(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback);

  PROPSHEET_UnImplementedFlags(lppsh->dwFlags);

  if (lppsh->dwFlags & INTRNL_ANY_WIZARD)
     psInfo->ppshheader.pszCaption = NULL;
  else
  {
     if (HIWORD(lppsh->pszCaption))
     {
        int len = strlenW(lppsh->pszCaption);
        psInfo->ppshheader.pszCaption = Alloc( (len+1)*sizeof(WCHAR) );
        strcpyW( (WCHAR *)psInfo->ppshheader.pszCaption, lppsh->pszCaption );
     }
  }
  psInfo->nPages = lppsh->nPages;

  if (dwFlags & PSH_USEPSTARTPAGE)
  {
    TRACE("PSH_USEPSTARTPAGE is on\n");
    psInfo->active_page = 0;
  }
  else
    psInfo->active_page = lppsh->u2.nStartPage;

  if (psInfo->active_page < 0 || psInfo->active_page >= psInfo->nPages)
     psInfo->active_page = 0;

  psInfo->result = 0;
  psInfo->hImageList = 0;
  psInfo->activeValid = FALSE;

  return TRUE;
}

/******************************************************************************
 *            PROPSHEET_CollectPageInfo
 *
 * Collect property sheet data.
 * With code taken from DIALOG_ParseTemplate32.
 */
static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp,
                               PropSheetInfo * psInfo,
                               int index)
{
  DLGTEMPLATE* pTemplate;
  const WORD*  p;
  DWORD dwFlags;
  int width, height;

  if (!lppsp)
    return FALSE;

  TRACE("\n");
  psInfo->proppage[index].hpage = (HPROPSHEETPAGE)lppsp;
  psInfo->proppage[index].hwndPage = 0;
  psInfo->proppage[index].isDirty = FALSE;

  /*
   * Process property page flags.
   */
  dwFlags = lppsp->dwFlags;
  psInfo->proppage[index].useCallback = (dwFlags & PSP_USECALLBACK) && (lppsp->pfnCallback);
  psInfo->proppage[index].hasHelp = dwFlags & PSP_HASHELP;
  psInfo->proppage[index].hasIcon = dwFlags & (PSP_USEHICON | PSP_USEICONID);

  /* as soon as we have a page with the help flag, set the sheet flag on */
  if (psInfo->proppage[index].hasHelp)
    psInfo->hasHelp = TRUE;

  /*
   * Process page template.
   */
  if (dwFlags & PSP_DLGINDIRECT)
    pTemplate = (DLGTEMPLATE*)lppsp->u.pResource;
  else if(dwFlags & PSP_INTERNAL_UNICODE )
  {
    HRSRC hResource = FindResourceW(lppsp->hInstance,
                                    lppsp->u.pszTemplate,
                                    (LPWSTR)RT_DIALOG);
    HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
                                     hResource);
    pTemplate = (LPDLGTEMPLATEW)LockResource(hTemplate);
  }
  else
  {
    HRSRC hResource = FindResourceA(lppsp->hInstance,
                                    (LPCSTR)lppsp->u.pszTemplate,
                                    (LPSTR)RT_DIALOG);
    HGLOBAL hTemplate = LoadResource(lppsp->hInstance,
                                     hResource);
    pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate);
  }

  /*
   * Extract the size of the page and the caption.
   */
  if (!pTemplate)
      return FALSE;

  p = (const WORD *)pTemplate;

  if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF)
  {
    /* DLGTEMPLATEEX (not defined in any std. header file) */

⌨️ 快捷键说明

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