Sync to Wine-20050725:

Vitaliy Margolen <wine-patch@kievinfo.com>
- Send CDDS_ITEMPOSTERASE | CDDS_PREPAINT notify.
Felix Nawothnig <felix.nawothnig@t-online.de>
- Move DPA and DSA functions out of comctl32undoc.c as they are
  documented by now.
- Fix some DPA functions so they pass the new tests.
- Don't invalidate the whole propsheet when the page is switched.
Dimi Paun <dimi@lattica.com>
- Silence uninitialized warnings.
Robert Shearman <rob@codeweavers.com>
- Call SetBkMode with the correct value from the NMTBCUSTOMDRAW
  structure.
- Don't fill the NMTBCUSTOMDRAW structure in again for
  CDDS_POSTPAINT.
- Remove redundant bBtnTransprnt value.
- Height is now calculated based on the number of rows, not on the
  bounding rect.
- Only call CalcToolbar in AutoSize if it has TBSTYLE_WRAPABLE or
  TBSTYLE_EX_UNDOC1 set.
- Remove a bad test in SetButtonWidth that fixes a regression from the
  above change in IE.
- Remove unnecessary nHeight data.
- Remove duplicated code in Size by calling AutoSize.
- Remove unnecessary bAutoSize value because SetWindowPos doesn't
  generate WM_SIZE when there is nothing to do on both Windows and
  Wine.
- TBSTATE_INDETERMINATE only takes effect if the button is enabled,
  otherwise it should just appear like any other disabled button.
- Native autosizes on inserting/adding buttons, so we should too.
- The IsValidImageList test is not needed because if it isn't a valid
  image list we will have set the bitmap width and height to 1 and it
  does the wrong thing when no buttons are present.
- The calculated button height should include the text height when no
  buttons are present.
- Handle CopyImage and other functions failing by not adding the icon
  and notifying the caller.
Thomas Weidenmueller <wine-patches@reactsoft.com>
- Support PSH_WIZARDHASFINISH in wizards.
- Correct tab order of the wizard buttons.
- Support PSM_IDTOINDEX.
Aric Stewart <aric@codeweavers.com>
- When adding an image copy the full previous buffer.
- Implement replacing an icon with one from a resource.
Kevin Koltzau <kevin@plop.org>
- Forward some header notifications to parent of listview.
Frank Richter <frank.richter@gmail.com>
- Enabled "tab" dialog texture for property sheet pages.
- Add theming support for header controls.
- Use theming for the ListView non-client area.
- Let property sheets update the cached system colors upon receiving
  WM_SYSCOLORCHANGE.
- Add theming for the up/down control.

svn path=/trunk/; revision=17326
This commit is contained in:
Gé van Geldorp 2005-08-12 16:31:56 +00:00
parent 420b109b72
commit e98f97ee9f
27 changed files with 1998 additions and 1705 deletions

View file

@ -13,13 +13,16 @@
<library>advapi32</library>
<library>gdi32</library>
<library>user32</library>
<library>uxtheme</library>
<library>winmm</library>
<file>animate.c</file>
<file>comboex.c</file>
<file>comctl32undoc.c</file>
<file>commctrl.c</file>
<file>datetime.c</file>
<file>dpa.c</file>
<file>draglist.c</file>
<file>dsa.c</file>
<file>flatsb.c</file>
<file>header.c</file>
<file>hotkey.c</file>

File diff suppressed because it is too large Load diff

View file

@ -37,9 +37,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Wizard"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "结束", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "下一步(&N) >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< 上一步(&B)", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "下一步(&N) >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "结束", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "取消", IDCANCEL,178,138,50,14
PUSHBUTTON "帮助", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -39,9 +39,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Prùvodce"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Dokonèit", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Dal¹í >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Zpìt", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Dal¹í >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Dokonèit", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Storno", IDCANCEL,178,138,50,14
PUSHBUTTON "Nápovìda", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -57,9 +57,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Wizard"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "&Beenden", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Weiter >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Zurück", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Weiter >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Beenden", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Abbrechen", IDCANCEL,178,138,50,14
PUSHBUTTON "&Hilfe", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Wizard"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Finish", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Next >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Back", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Next >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Finish", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Cancel", IDCANCEL,178,138,50,14
PUSHBUTTON "Help", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Ayudante"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Terminar", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Siguiente >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Anterior", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Siguiente >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Terminar", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Cancelar", IDCANCEL,178,138,50,14
PUSHBUTTON "Ayuda", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -40,9 +40,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Assistant"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Terminer", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Suivant >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Précédent", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Suivant >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Terminer", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Annuler", IDCANCEL,178,138,50,14
PUSHBUTTON "Aide", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -37,9 +37,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Wizard"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Fine", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Avanti >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Indietro", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Avanti >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Fine", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Anulla", IDCANCEL,178,138,50,14
PUSHBUTTON "Aiuto", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Wizard"
FONT 9, "MS UI Gothic"
BEGIN
DEFPUSHBUTTON "Š®—¹", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "<22>iÞ(&N) >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< 戻る(&B)", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "<22>iÞ(&N) >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Š®—¹", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "キャンセル", IDCANCEL,178,138,50,14
PUSHBUTTON "ヘルプ", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Wizard"
FONT 9, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "종료", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "다음(&N) >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< 이전(&B)", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "다음(&N) >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "종료", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "취소", IDCANCEL,178,138,50,14
PUSHBUTTON "도움말", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -38,9 +38,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Assistent"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Beëindigen", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Volgende >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< V&orige", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Volgende >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Beëindigen", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Annuleren", IDCANCEL,178,138,50,14
PUSHBUTTON "Help", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -37,9 +37,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Kreator"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Zakoñcz", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Dalej >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Wstecz", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Dalej >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Zakoñcz", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Anuluj", IDCANCEL,178,138,50,14
PUSHBUTTON "Pomoc", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Assistente"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Finalizar", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Avançar >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Voltar", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Avançar >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Finalizar", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Cancelar", IDCANCEL,178,138,50,14
PUSHBUTTON "Ajuda", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -38,9 +38,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Ìàñòåð"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Çàâåðøèòü", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Äàëåå >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Íàçàä", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Äàëåå >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Çàâåðøèòü", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Îòìåíà", IDCANCEL,178,138,50,14
PUSHBUTTON "&Ñïðàâêà", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Èarovnik"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Dokonèaj", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "Naprej >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< Na&zaj", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "Naprej >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Dokonèaj", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Preklièi", IDCANCEL,178,138,50,14
PUSHBUTTON "Pomoè", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Guide"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "Slutför", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Nästa >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Föregående", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Nästa >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "Slutför", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "Avbryt", IDCANCEL,178,138,50,14
PUSHBUTTON "Hjälp", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Wizard"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "·íÒãËéàÊÃç¨", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "µèÍä» >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< Âé͹¡ÅѺ", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "µèÍä» >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "·íÒãËéàÊÃç¨", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "¡àÅÔ¡", IDCANCEL,178,138,50,14
PUSHBUTTON "ªèÇÂàËÅÕÍ", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

View file

@ -38,9 +38,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
CAPTION "Ìàñòåð"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "&Çàâåðøèòè", IDC_FINISH_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Äàë³ >", IDC_NEXT_BUTTON,121,138,50,14
PUSHBUTTON "< &Íàçàä", IDC_BACK_BUTTON,71,138,50,14
DEFPUSHBUTTON "&Äàë³ >", IDC_NEXT_BUTTON,121,138,50,14
DEFPUSHBUTTON "&Çàâåðøèòè", IDC_FINISH_BUTTON,121,138,50,14
PUSHBUTTON "&³äì³íà", IDCANCEL,178,138,50,14
PUSHBUTTON "&Äîâ³äêà", IDHELP,235,138,50,14,WS_GROUP
LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN

973
reactos/lib/comctl32/dpa.c Normal file
View file

@ -0,0 +1,973 @@
/*
* Dynamic pointer array (DPA) implementation
*
* Copyright 1998 Eric Kohl
* 1998 Juergen Schmied <j.schmied@metronet.de>
* 2000 Eric Kohl for CodeWeavers
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* These functions were involuntarily documented by Microsoft in 2002 as
* the outcome of an anti-trust suit brought by various U.S. governments.
* As a result the specifications on MSDN are inaccurate, incomplete
* and misleading. A much more complete (unofficial) documentation is
* available at:
*
* http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32
*/
#define COBJMACROS
#include <stdarg.h>
#include <limits.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "commctrl.h"
#include "objbase.h"
#include "comctl32.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dpa);
struct _DPA
{
INT nItemCount;
LPVOID *ptrs;
HANDLE hHeap;
INT nGrow;
INT nMaxCount;
};
typedef struct _STREAMDATA
{
DWORD dwSize;
DWORD dwData2;
DWORD dwItems;
} STREAMDATA, *PSTREAMDATA;
typedef struct _LOADDATA
{
INT nCount;
PVOID ptr;
} LOADDATA, *LPLOADDATA;
typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
/**************************************************************************
* DPA_LoadStream [COMCTL32.9]
*
* Loads a dynamic pointer array from a stream
*
* PARAMS
* phDpa [O] pointer to a handle to a dynamic pointer array
* loadProc [I] pointer to a callback function
* pStream [I] pointer to a stream
* lParam [I] application specific value
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*
* NOTES
* No more information available yet!
*/
HRESULT WINAPI DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc,
IStream *pStream, LPARAM lParam)
{
HRESULT errCode;
LARGE_INTEGER position;
ULARGE_INTEGER newPosition;
STREAMDATA streamData;
LOADDATA loadData;
ULONG ulRead;
HDPA hDpa;
PVOID *ptr;
FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
phDpa, loadProc, pStream, lParam);
if (!phDpa || !loadProc || !pStream)
return E_INVALIDARG;
*phDpa = (HDPA)NULL;
position.QuadPart = 0;
/*
* Zero out our streamData
*/
memset(&streamData,0,sizeof(STREAMDATA));
errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
if (errCode != S_OK)
return errCode;
errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
if (errCode != S_OK)
return errCode;
FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n",
streamData.dwSize, streamData.dwData2, streamData.dwItems);
if ( ulRead < sizeof(STREAMDATA) ||
lParam < sizeof(STREAMDATA) ||
streamData.dwSize < sizeof(STREAMDATA) ||
streamData.dwData2 < 1) {
errCode = E_FAIL;
}
if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */
return E_OUTOFMEMORY;
/* create the dpa */
hDpa = DPA_Create (streamData.dwItems);
if (!hDpa)
return E_OUTOFMEMORY;
if (!DPA_Grow (hDpa, streamData.dwItems))
return E_OUTOFMEMORY;
/* load data from the stream into the dpa */
ptr = hDpa->ptrs;
for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
errCode = (loadProc)(&loadData, pStream, lParam);
if (errCode != S_OK) {
errCode = S_FALSE;
break;
}
*ptr = loadData.ptr;
ptr++;
}
/* set the number of items */
hDpa->nItemCount = loadData.nCount;
/* store the handle to the dpa */
*phDpa = hDpa;
FIXME ("new hDpa=%p, errorcode=%lx\n", hDpa, errCode);
return errCode;
}
/**************************************************************************
* DPA_SaveStream [COMCTL32.10]
*
* Saves a dynamic pointer array to a stream
*
* PARAMS
* hDpa [I] handle to a dynamic pointer array
* loadProc [I] pointer to a callback function
* pStream [I] pointer to a stream
* lParam [I] application specific value
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*
* NOTES
* No more information available yet!
*/
HRESULT WINAPI DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc,
IStream *pStream, LPARAM lParam)
{
FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
hDpa, loadProc, pStream, lParam);
return E_FAIL;
}
/**************************************************************************
* DPA_Merge [COMCTL32.11]
*
* Merge two dynamic pointers arrays.
*
* PARAMS
* hdpa1 [I] handle to a dynamic pointer array
* hdpa2 [I] handle to a dynamic pointer array
* dwFlags [I] flags
* pfnCompare [I] pointer to sort function
* pfnMerge [I] pointer to merge function
* lParam [I] application specific value
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*
* NOTES
* No more information available yet!
*/
BOOL WINAPI DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge,
LPARAM lParam)
{
INT nCount;
LPVOID *pWork1, *pWork2;
INT nResult, i;
INT nIndex;
TRACE("%p %p %08lx %p %p %08lx)\n",
hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
if (IsBadWritePtr (hdpa1, sizeof(*hdpa1)))
return FALSE;
if (IsBadWritePtr (hdpa2, sizeof(*hdpa2)))
return FALSE;
if (IsBadCodePtr ((FARPROC)pfnCompare))
return FALSE;
if (IsBadCodePtr ((FARPROC)pfnMerge))
return FALSE;
if (!(dwFlags & DPAM_NOSORT)) {
TRACE("sorting dpa's!\n");
if (hdpa1->nItemCount > 0)
DPA_Sort (hdpa1, pfnCompare, lParam);
TRACE ("dpa 1 sorted!\n");
if (hdpa2->nItemCount > 0)
DPA_Sort (hdpa2, pfnCompare, lParam);
TRACE ("dpa 2 sorted!\n");
}
if (hdpa2->nItemCount < 1)
return TRUE;
TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
hdpa1->nItemCount, hdpa2->nItemCount);
/* working but untrusted implementation */
pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
nIndex = hdpa1->nItemCount - 1;
nCount = hdpa2->nItemCount - 1;
do
{
if (nIndex < 0) {
if ((nCount >= 0) && (dwFlags & DPAM_INSERT)) {
/* Now insert the remaining new items into DPA 1 */
TRACE("%d items to be inserted at start of DPA 1\n",
nCount+1);
for (i=nCount; i>=0; i--) {
PVOID ptr;
ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
if (!ptr)
return FALSE;
DPA_InsertPtr (hdpa1, 0, ptr);
pWork2--;
}
}
break;
}
nResult = (pfnCompare)(*pWork1, *pWork2, lParam);
TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
nResult, nIndex, nCount);
if (nResult == 0)
{
PVOID ptr;
ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam);
if (!ptr)
return FALSE;
nCount--;
pWork2--;
*pWork1 = ptr;
nIndex--;
pWork1--;
}
else if (nResult > 0)
{
/* item in DPA 1 missing from DPA 2 */
if (dwFlags & DPAM_DELETE)
{
/* Now delete the extra item in DPA1 */
PVOID ptr;
ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
(pfnMerge)(2, ptr, NULL, lParam);
}
nIndex--;
pWork1--;
}
else
{
/* new item in DPA 2 */
if (dwFlags & DPAM_INSERT)
{
/* Now insert the new item in DPA 1 */
PVOID ptr;
ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
if (!ptr)
return FALSE;
DPA_InsertPtr (hdpa1, nIndex+1, ptr);
}
nCount--;
pWork2--;
}
}
while (nCount >= 0);
return TRUE;
}
/**************************************************************************
* DPA_Destroy [COMCTL32.329]
*
* Destroys a dynamic pointer array
*
* PARAMS
* hdpa [I] handle (pointer) to the pointer array
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DPA_Destroy (const HDPA hdpa)
{
TRACE("(%p)\n", hdpa);
if (!hdpa)
return FALSE;
if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
return FALSE;
return HeapFree (hdpa->hHeap, 0, hdpa);
}
/**************************************************************************
* DPA_Grow [COMCTL32.330]
*
* Sets the growth amount.
*
* PARAMS
* hdpa [I] handle (pointer) to the existing (source) pointer array
* nGrow [I] number of items by which the array grows when it's too small
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DPA_Grow (const HDPA hdpa, INT nGrow)
{
TRACE("(%p %d)\n", hdpa, nGrow);
if (!hdpa)
return FALSE;
hdpa->nGrow = max(8, nGrow);
return TRUE;
}
/**************************************************************************
* DPA_Clone [COMCTL32.331]
*
* Copies a pointer array to an other one or creates a copy
*
* PARAMS
* hdpa [I] handle (pointer) to the existing (source) pointer array
* hdpaNew [O] handle (pointer) to the destination pointer array
*
* RETURNS
* Success: pointer to the destination pointer array.
* Failure: NULL
*
* NOTES
* - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
* array will be created and it's handle (pointer) is returned.
* - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
* this implementation just returns NULL.
*/
HDPA WINAPI DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
{
INT nNewItems, nSize;
HDPA hdpaTemp;
if (!hdpa)
return NULL;
TRACE("(%p %p)\n", hdpa, hdpaNew);
if (!hdpaNew) {
/* create a new DPA */
hdpaTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
sizeof(*hdpaTemp));
hdpaTemp->hHeap = hdpa->hHeap;
hdpaTemp->nGrow = hdpa->nGrow;
}
else
hdpaTemp = hdpaNew;
if (hdpaTemp->ptrs) {
/* remove old pointer array */
HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
hdpaTemp->ptrs = NULL;
hdpaTemp->nItemCount = 0;
hdpaTemp->nMaxCount = 0;
}
/* create a new pointer array */
nNewItems = hdpaTemp->nGrow *
((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
nSize = nNewItems * sizeof(LPVOID);
hdpaTemp->ptrs = HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
hdpaTemp->nMaxCount = nNewItems;
/* clone the pointer array */
hdpaTemp->nItemCount = hdpa->nItemCount;
memmove (hdpaTemp->ptrs, hdpa->ptrs,
hdpaTemp->nItemCount * sizeof(LPVOID));
return hdpaTemp;
}
/**************************************************************************
* DPA_GetPtr [COMCTL32.332]
*
* Retrieves a pointer from a dynamic pointer array
*
* PARAMS
* hdpa [I] handle (pointer) to the pointer array
* nIndex [I] array index of the desired pointer
*
* RETURNS
* Success: pointer
* Failure: NULL
*/
LPVOID WINAPI DPA_GetPtr (const HDPA hdpa, INT nIndex)
{
TRACE("(%p %d)\n", hdpa, nIndex);
if (!hdpa)
return NULL;
if (!hdpa->ptrs) {
WARN("no pointer array.\n");
return NULL;
}
if ((nIndex < 0) || (nIndex >= hdpa->nItemCount)) {
WARN("not enough pointers in array (%d vs %d).\n",nIndex,hdpa->nItemCount);
return NULL;
}
TRACE("-- %p\n", hdpa->ptrs[nIndex]);
return hdpa->ptrs[nIndex];
}
/**************************************************************************
* DPA_GetPtrIndex [COMCTL32.333]
*
* Retrieves the index of the specified pointer
*
* PARAMS
* hdpa [I] handle (pointer) to the pointer array
* p [I] pointer
*
* RETURNS
* Success: index of the specified pointer
* Failure: -1
*/
INT WINAPI DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
{
INT i;
if (!hdpa || !hdpa->ptrs)
return -1;
for (i = 0; i < hdpa->nItemCount; i++) {
if (hdpa->ptrs[i] == p)
return i;
}
return -1;
}
/**************************************************************************
* DPA_InsertPtr [COMCTL32.334]
*
* Inserts a pointer into a dynamic pointer array
*
* PARAMS
* hdpa [I] handle (pointer) to the array
* i [I] array index
* p [I] pointer to insert
*
* RETURNS
* Success: index of the inserted pointer
* Failure: -1
*/
INT WINAPI DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
{
TRACE("(%p %d %p)\n", hdpa, i, p);
if (!hdpa || i < 0) return -1;
/* append item if index is out of bounds */
i = min(hdpa->nItemCount, i);
/* create empty spot at the end */
if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1;
if (i != hdpa->nItemCount - 1)
memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i,
(hdpa->nItemCount - i - 1) * sizeof(LPVOID));
hdpa->ptrs[i] = p;
return i;
}
/**************************************************************************
* DPA_SetPtr [COMCTL32.335]
*
* Sets a pointer in the pointer array
*
* PARAMS
* hdpa [I] handle (pointer) to the pointer array
* i [I] index of the pointer that will be set
* p [I] pointer to be set
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
{
LPVOID *lpTemp;
TRACE("(%p %d %p)\n", hdpa, i, p);
if (!hdpa || i < 0)
return FALSE;
if (hdpa->nItemCount <= i) {
/* within the old array */
if (hdpa->nMaxCount <= i) {
/* resize the block of memory */
INT nNewItems =
hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1);
INT nSize = nNewItems * sizeof(LPVOID);
if (hdpa->ptrs)
lpTemp = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize);
else
lpTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize);
if (!lpTemp)
return FALSE;
hdpa->nMaxCount = nNewItems;
hdpa->ptrs = lpTemp;
}
hdpa->nItemCount = i+1;
}
/* put the new entry in */
hdpa->ptrs[i] = p;
return TRUE;
}
/**************************************************************************
* DPA_DeletePtr [COMCTL32.336]
*
* Removes a pointer from the pointer array.
*
* PARAMS
* hdpa [I] handle (pointer) to the pointer array
* i [I] index of the pointer that will be deleted
*
* RETURNS
* Success: deleted pointer
* Failure: NULL
*/
LPVOID WINAPI DPA_DeletePtr (const HDPA hdpa, INT i)
{
LPVOID *lpDest, *lpSrc, lpTemp = NULL;
INT nSize;
TRACE("(%p %d)\n", hdpa, i);
if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
return NULL;
lpTemp = hdpa->ptrs[i];
/* do we need to move ?*/
if (i < hdpa->nItemCount - 1) {
lpDest = hdpa->ptrs + i;
lpSrc = lpDest + 1;
nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
TRACE("-- move dest=%p src=%p size=%x\n",
lpDest, lpSrc, nSize);
memmove (lpDest, lpSrc, nSize);
}
hdpa->nItemCount --;
/* free memory ?*/
if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount);
nSize = nNewItems * sizeof(LPVOID);
lpDest = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
hdpa->ptrs, nSize);
if (!lpDest)
return NULL;
hdpa->nMaxCount = nNewItems;
hdpa->ptrs = (LPVOID*)lpDest;
}
return lpTemp;
}
/**************************************************************************
* DPA_DeleteAllPtrs [COMCTL32.337]
*
* Removes all pointers and reinitializes the array.
*
* PARAMS
* hdpa [I] handle (pointer) to the pointer array
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DPA_DeleteAllPtrs (const HDPA hdpa)
{
TRACE("(%p)\n", hdpa);
if (!hdpa)
return FALSE;
if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
return FALSE;
hdpa->nItemCount = 0;
hdpa->nMaxCount = hdpa->nGrow * 2;
hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
hdpa->nMaxCount * sizeof(LPVOID));
return TRUE;
}
/**************************************************************************
* DPA_QuickSort [Internal]
*
* Ordinary quicksort (used by DPA_Sort).
*
* PARAMS
* lpPtrs [I] pointer to the pointer array
* l [I] index of the "left border" of the partition
* r [I] index of the "right border" of the partition
* pfnCompare [I] pointer to the compare function
* lParam [I] user defined value (3rd parameter in compare function)
*
* RETURNS
* NONE
*/
static VOID DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
PFNDPACOMPARE pfnCompare, LPARAM lParam)
{
INT m;
LPVOID t;
TRACE("l=%i r=%i\n", l, r);
if (l==r) /* one element is always sorted */
return;
if (r<l) /* oops, got it in the wrong order */
{
DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
return;
}
m = (l+r)/2; /* divide by two */
DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam);
DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam);
/* join the two sides */
while( (l<=m) && (m<r) )
{
if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0)
{
t = lpPtrs[m+1];
memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof(lpPtrs[l]));
lpPtrs[l] = t;
m++;
}
l++;
}
}
/**************************************************************************
* DPA_Sort [COMCTL32.338]
*
* Sorts a pointer array using a user defined compare function
*
* PARAMS
* hdpa [I] handle (pointer) to the pointer array
* pfnCompare [I] pointer to the compare function
* lParam [I] user defined value (3rd parameter of compare function)
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
{
if (!hdpa || !pfnCompare)
return FALSE;
TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
pfnCompare, lParam);
return TRUE;
}
/**************************************************************************
* DPA_Search [COMCTL32.339]
*
* Searches a pointer array for a specified pointer
*
* PARAMS
* hdpa [I] handle (pointer) to the pointer array
* pFind [I] pointer to search for
* nStart [I] start index
* pfnCompare [I] pointer to the compare function
* lParam [I] user defined value (3rd parameter of compare function)
* uOptions [I] search options
*
* RETURNS
* Success: index of the pointer in the array.
* Failure: -1
*
* NOTES
* Binary search taken from R.Sedgewick "Algorithms in C"!
* Function is NOT tested!
* If something goes wrong, blame HIM not ME! (Eric Kohl)
*/
INT WINAPI DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
{
if (!hdpa || !pfnCompare || !pFind)
return -1;
TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
if (uOptions & DPAS_SORTED) {
/* array is sorted --> use binary search */
INT l, r, x, n;
LPVOID *lpPtr;
TRACE("binary search\n");
l = (nStart == -1) ? 0 : nStart;
r = hdpa->nItemCount - 1;
lpPtr = hdpa->ptrs;
while (r >= l) {
x = (l + r) / 2;
n = (pfnCompare)(pFind, lpPtr[x], lParam);
if (n < 0)
r = x - 1;
else
l = x + 1;
if (n == 0) {
TRACE("-- ret=%d\n", n);
return n;
}
}
if (uOptions & (DPAS_INSERTBEFORE | DPAS_INSERTAFTER)) {
TRACE("-- ret=%d\n", l);
return l;
}
}
else {
/* array is not sorted --> use linear search */
LPVOID *lpPtr;
INT nIndex;
TRACE("linear search\n");
nIndex = (nStart == -1)? 0 : nStart;
lpPtr = hdpa->ptrs;
for (; nIndex < hdpa->nItemCount; nIndex++) {
if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
TRACE("-- ret=%d\n", nIndex);
return nIndex;
}
}
}
TRACE("-- not found: ret=-1\n");
return -1;
}
/**************************************************************************
* DPA_CreateEx [COMCTL32.340]
*
* Creates a dynamic pointer array using the specified size and heap.
*
* PARAMS
* nGrow [I] number of items by which the array grows when it is filled
* hHeap [I] handle to the heap where the array is stored
*
* RETURNS
* Success: handle (pointer) to the pointer array.
* Failure: NULL
*
* NOTES
* The DPA_ functions can be used to create and manipulate arrays of
* pointers.
*/
HDPA WINAPI DPA_CreateEx (INT nGrow, HANDLE hHeap)
{
HDPA hdpa;
TRACE("(%d %p)\n", nGrow, hHeap);
if (hHeap)
hdpa = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(*hdpa));
else
hdpa = Alloc (sizeof(*hdpa));
if (hdpa) {
hdpa->nGrow = max(8, nGrow);
hdpa->hHeap = hHeap ? hHeap : GetProcessHeap();
hdpa->nMaxCount = hdpa->nGrow * 2;
hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
hdpa->nMaxCount * sizeof(LPVOID));
}
TRACE("-- %p\n", hdpa);
return hdpa;
}
/**************************************************************************
* DPA_Create [COMCTL32.328]
*
* Creates a dynamic pointer array.
*
* PARAMS
* nGrow [I] number of items by which the array grows when it is filled
*
* RETURNS
* Success: handle (pointer) to the pointer array.
* Failure: NULL
*
* NOTES
* The DPA_ functions can be used to create and manipulate arrays of
* pointers.
*/
HDPA WINAPI DPA_Create (INT nGrow)
{
return DPA_CreateEx( nGrow, 0 );
}
/**************************************************************************
* DPA_EnumCallback [COMCTL32.385]
*
* Enumerates all items in a dynamic pointer array.
*
* PARAMS
* hdpa [I] handle to the dynamic pointer array
* enumProc [I]
* lParam [I]
*
* RETURNS
* none
*/
VOID WINAPI DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc,
LPVOID lParam)
{
INT i;
TRACE("(%p %p %p)\n", hdpa, enumProc, lParam);
if (!hdpa)
return;
if (hdpa->nItemCount <= 0)
return;
for (i = 0; i < hdpa->nItemCount; i++) {
if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
return;
}
return;
}
/**************************************************************************
* DPA_DestroyCallback [COMCTL32.386]
*
* Enumerates all items in a dynamic pointer array and destroys it.
*
* PARAMS
* hdpa [I] handle to the dynamic pointer array
* enumProc [I]
* lParam [I]
*
* RETURNS
* none
*/
void WINAPI DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc,
LPVOID lParam)
{
TRACE("(%p %p %p)\n", hdpa, enumProc, lParam);
DPA_EnumCallback (hdpa, enumProc, lParam);
DPA_Destroy (hdpa);
}

436
reactos/lib/comctl32/dsa.c Normal file
View file

@ -0,0 +1,436 @@
/*
* Dynamic structure array (DSA) implementation
*
* Copyright 1998 Eric Kohl
* 1998 Juergen Schmied <j.schmied@metronet.de>
* 2000 Eric Kohl for CodeWeavers
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES
* These functions were involuntarily documented by Microsoft in 2002 as
* the outcome of an anti-trust suit brought by various U.S. governments.
* As a result the specifications on MSDN are inaccurate, incomplete
* and misleading. A much more complete (unofficial) documentation is
* available at:
*
* http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "commctrl.h"
#include "comctl32.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsa);
struct _DSA
{
INT nItemCount;
LPVOID pData;
INT nMaxCount;
INT nItemSize;
INT nGrow;
};
/**************************************************************************
* DSA_Create [COMCTL32.320]
*
* Creates a dynamic storage array
*
* PARAMS
* nSize [I] size of the array elements
* nGrow [I] number of elements by which the array grows when it is filled
*
* RETURNS
* Success: pointer to an array control structure. Use this like a handle.
* Failure: NULL
*
* NOTES
* The DSA_ functions can be used to create and manipulate arrays of
* fixed-size memory blocks. These arrays can store any kind of data
* (e.g. strings and icons).
*/
HDSA WINAPI DSA_Create (INT nSize, INT nGrow)
{
HDSA hdsa;
TRACE("(size=%d grow=%d)\n", nSize, nGrow);
hdsa = Alloc (sizeof(*hdsa));
if (hdsa)
{
hdsa->nItemCount = 0;
hdsa->pData = NULL;
hdsa->nMaxCount = 0;
hdsa->nItemSize = nSize;
hdsa->nGrow = max(1, nGrow);
}
return hdsa;
}
/**************************************************************************
* DSA_Destroy [COMCTL32.321]
*
* Destroys a dynamic storage array
*
* PARAMS
* hdsa [I] pointer to the array control structure
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DSA_Destroy (const HDSA hdsa)
{
TRACE("(%p)\n", hdsa);
if (!hdsa)
return FALSE;
if (hdsa->pData && (!Free (hdsa->pData)))
return FALSE;
return Free (hdsa);
}
/**************************************************************************
* DSA_GetItem [COMCTL32.322]
*
* Copies the specified item into a caller-supplied buffer.
*
* PARAMS
* hdsa [I] pointer to the array control structure
* nIndex [I] number of the Item to get
* pDest [O] destination buffer. Has to be >= dwElementSize.
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
{
LPVOID pSrc;
TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
if (!hdsa)
return FALSE;
if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
return FALSE;
pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
memmove (pDest, pSrc, hdsa->nItemSize);
return TRUE;
}
/**************************************************************************
* DSA_GetItemPtr [COMCTL32.323]
*
* Retrieves a pointer to the specified item.
*
* PARAMS
* hdsa [I] pointer to the array control structure
* nIndex [I] index of the desired item
*
* RETURNS
* Success: pointer to an item
* Failure: NULL
*/
LPVOID WINAPI DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
{
LPVOID pSrc;
TRACE("(%p %d)\n", hdsa, nIndex);
if (!hdsa)
return NULL;
if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
return NULL;
pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
TRACE("-- ret=%p\n", pSrc);
return pSrc;
}
/**************************************************************************
* DSA_SetItem [COMCTL32.325]
*
* Sets the contents of an item in the array.
*
* PARAMS
* hdsa [I] pointer to the array control structure
* nIndex [I] index for the item
* pSrc [I] pointer to the new item data
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
{
INT nSize, nNewItems;
LPVOID pDest, lpTemp;
TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
if ((!hdsa) || nIndex < 0)
return FALSE;
if (hdsa->nItemCount <= nIndex) {
/* within the old array */
if (hdsa->nMaxCount > nIndex) {
/* within the allocated space, set a new boundary */
hdsa->nItemCount = nIndex + 1;
}
else {
/* resize the block of memory */
nNewItems =
hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
nSize = hdsa->nItemSize * nNewItems;
lpTemp = ReAlloc (hdsa->pData, nSize);
if (!lpTemp)
return FALSE;
hdsa->nMaxCount = nNewItems;
hdsa->nItemCount = nIndex + 1;
hdsa->pData = lpTemp;
}
}
/* put the new entry in */
pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
TRACE("-- move dest=%p src=%p size=%d\n",
pDest, pSrc, hdsa->nItemSize);
memmove (pDest, pSrc, hdsa->nItemSize);
return TRUE;
}
/**************************************************************************
* DSA_InsertItem [COMCTL32.324]
*
* Inserts an item into the array at the specified index.
*
* PARAMS
* hdsa [I] pointer to the array control structure
* nIndex [I] index for the new item
* pSrc [I] pointer to the element
*
* RETURNS
* Success: position of the new item
* Failure: -1
*/
INT WINAPI DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
{
INT nNewItems, nSize;
LPVOID lpTemp, lpDest;
TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
if ((!hdsa) || nIndex < 0)
return -1;
/* when nIndex >= nItemCount then append */
if (nIndex >= hdsa->nItemCount)
nIndex = hdsa->nItemCount;
/* do we need to resize ? */
if (hdsa->nItemCount >= hdsa->nMaxCount) {
nNewItems = hdsa->nMaxCount + hdsa->nGrow;
nSize = hdsa->nItemSize * nNewItems;
lpTemp = ReAlloc (hdsa->pData, nSize);
if (!lpTemp)
return -1;
hdsa->nMaxCount = nNewItems;
hdsa->pData = lpTemp;
}
/* do we need to move elements ? */
if (nIndex < hdsa->nItemCount) {
lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
lpDest = (char *) lpTemp + hdsa->nItemSize;
nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
TRACE("-- move dest=%p src=%p size=%d\n",
lpDest, lpTemp, nSize);
memmove (lpDest, lpTemp, nSize);
}
/* ok, we can put the new Item in */
hdsa->nItemCount++;
lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
TRACE("-- move dest=%p src=%p size=%d\n",
lpDest, pSrc, hdsa->nItemSize);
memmove (lpDest, pSrc, hdsa->nItemSize);
return nIndex;
}
/**************************************************************************
* DSA_DeleteItem [COMCTL32.326]
*
* Deletes the specified item from the array.
*
* PARAMS
* hdsa [I] pointer to the array control structure
* nIndex [I] index for the element to delete
*
* RETURNS
* Success: number of the deleted element
* Failure: -1
*/
INT WINAPI DSA_DeleteItem (const HDSA hdsa, INT nIndex)
{
LPVOID lpDest,lpSrc;
INT nSize;
TRACE("(%p %d)\n", hdsa, nIndex);
if (!hdsa)
return -1;
if (nIndex < 0 || nIndex >= hdsa->nItemCount)
return -1;
/* do we need to move ? */
if (nIndex < hdsa->nItemCount - 1) {
lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
lpSrc = (char *) lpDest + hdsa->nItemSize;
nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
TRACE("-- move dest=%p src=%p size=%d\n",
lpDest, lpSrc, nSize);
memmove (lpDest, lpSrc, nSize);
}
hdsa->nItemCount--;
/* free memory ? */
if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
nSize = hdsa->nItemSize * hdsa->nItemCount;
lpDest = ReAlloc (hdsa->pData, nSize);
if (!lpDest)
return -1;
hdsa->nMaxCount = hdsa->nItemCount;
hdsa->pData = lpDest;
}
return nIndex;
}
/**************************************************************************
* DSA_DeleteAllItems [COMCTL32.327]
*
* Removes all items and reinitializes the array.
*
* PARAMS
* hdsa [I] pointer to the array control structure
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DSA_DeleteAllItems (const HDSA hdsa)
{
TRACE("(%p)\n", hdsa);
if (!hdsa)
return FALSE;
if (hdsa->pData && (!Free (hdsa->pData)))
return FALSE;
hdsa->nItemCount = 0;
hdsa->pData = NULL;
hdsa->nMaxCount = 0;
return TRUE;
}
/**************************************************************************
* DSA_EnumCallback [COMCTL32.387]
*
* Enumerates all items in a dynamic storage array.
*
* PARAMS
* hdsa [I] handle to the dynamic storage array
* enumProc [I]
* lParam [I]
*
* RETURNS
* none
*/
VOID WINAPI DSA_EnumCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc,
LPVOID lParam)
{
INT i;
TRACE("(%p %p %p)\n", hdsa, enumProc, lParam);
if (!hdsa)
return;
if (hdsa->nItemCount <= 0)
return;
for (i = 0; i < hdsa->nItemCount; i++) {
LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
if ((enumProc)(lpItem, lParam) == 0)
return;
}
return;
}
/**************************************************************************
* DSA_DestroyCallback [COMCTL32.388]
*
* Enumerates all items in a dynamic storage array and destroys it.
*
* PARAMS
* hdsa [I] handle to the dynamic storage array
* enumProc [I]
* lParam [I]
*
* RETURNS
* none
*/
void WINAPI DSA_DestroyCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc,
LPVOID lParam)
{
TRACE("(%p %p %p)\n", hdsa, enumProc, lParam);
DSA_EnumCallback (hdsa, enumProc, lParam);
DSA_Destroy (hdsa);
}

View file

@ -43,6 +43,8 @@
#include "commctrl.h"
#include "comctl32.h"
#include "imagelist.h"
#include "tmschema.h"
#include "uxtheme.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(header);
@ -94,6 +96,8 @@ typedef struct
#define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongPtrW(hwnd,0))
static const WCHAR themeClass[] = {'H','e','a','d','e','r',0};
inline static LRESULT
HEADER_IndexToOrder (HWND hwnd, INT iItem)
@ -164,6 +168,7 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack)
HEADER_ITEM *phdi = &infoPtr->items[iItem];
RECT r;
INT oldBkMode, cxEdge = GetSystemMetrics(SM_CXEDGE);
HTHEME theme = GetWindowTheme (hwnd);
TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem, bHotTrack, infoPtr->bUnicode);
@ -174,25 +179,52 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack)
if (r.right - r.left == 0)
return phdi->rect.right;
if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS) {
if (phdi->bDown) {
DrawEdge (hdc, &r, BDR_RAISEDOUTER,
BF_RECT | BF_FLAT | BF_MIDDLE | BF_ADJUST);
r.left += 2;
r.top += 2;
}
else
DrawEdge (hdc, &r, EDGE_RAISED,
BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
if (theme != NULL) {
int state = (phdi->bDown) ? HIS_PRESSED :
(bHotTrack ? HIS_HOT : HIS_NORMAL);
DrawThemeBackground (theme, hdc, HP_HEADERITEM, state,
&r, NULL);
GetThemeBackgroundContentRect (theme, hdc, HP_HEADERITEM, state,
&r, &r);
}
else {
if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS) {
if (phdi->bDown) {
DrawEdge (hdc, &r, BDR_RAISEDOUTER,
BF_RECT | BF_FLAT | BF_MIDDLE | BF_ADJUST);
}
else
DrawEdge (hdc, &r, EDGE_RAISED,
BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
}
else
DrawEdge (hdc, &r, EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST);
}
if (phdi->bDown) {
r.left += 2;
r.top += 2;
}
else
DrawEdge (hdc, &r, EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST);
r.left -= cxEdge;
r.right += cxEdge;
if (phdi->fmt & HDF_OWNERDRAW) {
DRAWITEMSTRUCT dis;
NMCUSTOMDRAW nmcd;
nmcd.hdr.hwndFrom = hwnd;
nmcd.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID);
nmcd.hdr.code = NM_CUSTOMDRAW;
nmcd.dwDrawStage = CDDS_PREPAINT | CDDS_ITEM | CDDS_ITEMPOSTERASE;
nmcd.hdc = hdc;
nmcd.dwItemSpec = iItem;
nmcd.rc = r;
nmcd.uItemState = phdi->bDown ? CDIS_SELECTED : 0;
nmcd.lItemlParam = phdi->lParam;
SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM)nmcd.hdr.idFrom, (LPARAM)&nmcd);
dis.CtlType = ODT_HEADER;
dis.CtlID = GetWindowLongPtrW (hwnd, GWLP_ID);
dis.itemID = iItem;
@ -315,7 +347,7 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack)
HDF_BITMAP_ON_RIGHT|HDF_IMAGE)))) /* no explicit format specified? */
&& (phdi->pszText)) {
oldBkMode = SetBkMode(hdc, TRANSPARENT);
SetTextColor (hdc, (bHotTrack) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT);
SetTextColor (hdc, (bHotTrack && !theme) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT);
r.left = tx;
r.right = tx + tw;
DrawTextW (hdc, phdi->pszText, -1,
@ -338,6 +370,7 @@ HEADER_Refresh (HWND hwnd, HDC hdc)
HBRUSH hbrBk;
UINT i;
INT x;
HTHEME theme = GetWindowTheme (hwnd);
/* get rect for the bar, adjusted for the border */
GetClientRect (hwnd, &rect);
@ -346,20 +379,29 @@ HEADER_Refresh (HWND hwnd, HDC hdc)
hOldFont = SelectObject (hdc, hFont);
/* draw Background */
hbrBk = GetSysColorBrush(COLOR_3DFACE);
FillRect(hdc, &rect, hbrBk);
if (theme == NULL) {
hbrBk = GetSysColorBrush(COLOR_3DFACE);
FillRect(hdc, &rect, hbrBk);
}
x = rect.left;
for (i = 0; i < infoPtr->uNumItem; i++) {
x = HEADER_DrawItem (hwnd, hdc, HEADER_OrderToIndex(hwnd,i), FALSE);
x = HEADER_DrawItem (hwnd, hdc, HEADER_OrderToIndex(hwnd,i),
infoPtr->iHotItem == i);
}
if ((x <= rect.right) && (infoPtr->uNumItem > 0)) {
rect.left = x;
if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS)
DrawEdge (hdc, &rect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT);
else
DrawEdge (hdc, &rect, EDGE_ETCHED, BF_BOTTOM);
if (theme != NULL) {
DrawThemeBackground (theme, hdc, HP_HEADERITEM, HIS_NORMAL, &rect,
NULL);
}
else {
if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS)
DrawEdge (hdc, &rect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT);
else
DrawEdge (hdc, &rect, EDGE_ETCHED, BF_BOTTOM);
}
}
SelectObject (hdc, hOldFont);
@ -1278,6 +1320,7 @@ HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
TEXTMETRICW tm;
HFONT hOldFont;
HDC hdc;
BOOL themingActive = IsAppThemed() && IsThemeActive();
infoPtr = (HEADER_INFO *)Alloc (sizeof(HEADER_INFO));
SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
@ -1307,6 +1350,8 @@ HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
SelectObject (hdc, hOldFont);
ReleaseDC (0, hdc);
if (themingActive) OpenThemeData(hwnd, themeClass);
return 0;
}
@ -1317,6 +1362,7 @@ HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
HEADER_ITEM *lpItem;
INT nItem;
HTHEME theme;
if (infoPtr->items) {
lpItem = infoPtr->items;
@ -1332,6 +1378,9 @@ HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
SetWindowLongPtrW (hwnd, 0, 0);
Free (infoPtr);
theme = GetWindowTheme(hwnd);
CloseThemeData(theme);
return 0;
}
@ -1692,6 +1741,16 @@ HEADER_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
return 0;
}
/* Update the theme handle after a theme change */
static LRESULT HEADER_ThemeChanged(HWND hwnd)
{
HTHEME theme = GetWindowTheme(hwnd);
CloseThemeData(theme);
OpenThemeData(hwnd, themeClass);
InvalidateRect(hwnd, NULL, FALSE);
return 0;
}
static LRESULT WINAPI
HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
@ -1804,6 +1863,9 @@ HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_SIZE:
return HEADER_Size (hwnd, wParam);
case WM_THEMECHANGED:
return HEADER_ThemeChanged (hwnd);
case WM_PAINT:
return HEADER_Paint (hwnd, wParam);

View file

@ -2226,25 +2226,51 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
HBITMAP hbmOldSrc;
ICONINFO ii;
BITMAP bmp;
BOOL ret;
TRACE("(%p %d %p)\n", himl, i, hIcon);
if (!is_valid(himl))
return -1;
if ((i >= himl->cMaxImage) || (i < -1))
return -1;
if (!is_valid(himl)) {
ERR("invalid image list\n");
return -1;
}
if ((i >= himl->cMaxImage) || (i < -1)) {
ERR("invalid image index %d / %d\n", i, himl->cMaxImage);
return -1;
}
hBestFitIcon = CopyImage(
hIcon, IMAGE_ICON,
himl->cx, himl->cy,
LR_COPYFROMRESOURCE);
/* the above will fail if the icon wasn't loaded from a resource, so try
* again without LR_COPYFROMRESOURCE flag */
if (!hBestFitIcon)
hBestFitIcon = CopyImage(
hIcon, IMAGE_ICON,
himl->cx, himl->cy,
0);
if (!hBestFitIcon)
return -1;
ret = GetIconInfo (hBestFitIcon, &ii);
if (!ret) {
DestroyIcon(hBestFitIcon);
return -1;
}
GetIconInfo (hBestFitIcon, &ii);
if (ii.hbmMask == 0)
ERR("no mask!\n");
if (ii.hbmColor == 0)
ERR("no color!\n");
GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
ret = GetObjectW (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
if (!ret) {
ERR("couldn't get mask bitmap info\n");
if (ii.hbmColor)
DeleteObject (ii.hbmColor);
if (ii.hbmMask)
DeleteObject (ii.hbmMask);
DestroyIcon(hBestFitIcon);
return -1;
}
if (i == -1) {
if (himl->cCurImage + 1 > himl->cMaxImage)
@ -2276,8 +2302,7 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
SelectObject (hdcImage, hbmOldSrc);
if(hBestFitIcon)
DestroyIcon(hBestFitIcon);
DestroyIcon(hBestFitIcon);
if (hdcImage)
DeleteDC (hdcImage);
if (ii.hbmColor)

View file

@ -185,6 +185,7 @@
#include "winnls.h"
#include "commctrl.h"
#include "comctl32.h"
#include "uxtheme.h"
#include "wine/debug.h"
#include "wine/unicode.h"
@ -396,6 +397,8 @@ typedef struct tagLISTVIEW_INFO
TRACE("hwndSelf=%p, rcList=%s\n", iP->hwndSelf, debugrect(&iP->rcList)); \
} while(0)
static const WCHAR themeClass[] = {'L','i','s','t','V','i','e','w',0};
/*
* forward declarations
*/
@ -740,6 +743,12 @@ static inline LPCSTR debugscrollcode(int nScrollCode)
/******** Notification functions i************************************/
static LRESULT notify_forward_header(LISTVIEW_INFO *infoPtr, const NMHEADERW *lpnmh)
{
return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM)lpnmh->hdr.idFrom, (LPARAM)lpnmh);
}
static LRESULT notify_hdr(LISTVIEW_INFO *infoPtr, INT code, LPNMHDR pnmh)
{
LRESULT result;
@ -1967,6 +1976,7 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI
if (lprcState) *lprcState = State;
TRACE(" - state=%s\n", debugrect(&State));
}
else State.right = 0;
/************************************************************/
/* compute ICON bounding box (ala LVM_GETITEMRECT) */
@ -1989,7 +1999,7 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI
}
else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */
{
Icon.left = State.right;
Icon.left = State.right;
Icon.top = Box.top;
Icon.right = Icon.left;
if (infoPtr->himlSmall &&
@ -2001,6 +2011,7 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI
if(lprcIcon) *lprcIcon = Icon;
TRACE(" - icon=%s\n", debugrect(&Icon));
}
else Icon.right = 0;
/************************************************************/
/* compute LABEL bounding box (ala LVM_GETITEMRECT) */
@ -4812,6 +4823,7 @@ static INT LISTVIEW_FindItemW(LISTVIEW_INFO *infoPtr, INT nStart,
}
bNearest = TRUE;
}
else Destination.x = Destination.y = 0;
/* if LVFI_PARAM is specified, all other flags are ignored */
if (lpFindInfo->flags & LVFI_PARAM)
@ -7444,6 +7456,25 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare,
return TRUE;
}
/***
* DESCRIPTION:
* Update theme handle after a theme change.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
*
* RETURN:
* SUCCESS : 0
* FAILURE : something else
*/
static LRESULT LISTVIEW_ThemeChanged(LISTVIEW_INFO *infoPtr)
{
HTHEME theme = GetWindowTheme(infoPtr->hwndSelf);
CloseThemeData(theme);
OpenThemeData(infoPtr->hwndSelf, themeClass);
return 0;
}
/***
* DESCRIPTION:
* Updates an items or rearranges the listview control.
@ -7489,6 +7520,7 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
LISTVIEW_INFO *infoPtr;
UINT uView = lpcs->style & LVS_TYPEMASK;
LOGFONTW logFont;
BOOL themingActive = IsAppThemed() && IsThemeActive();
TRACE("(lpcs=%p)\n", lpcs);
@ -7571,6 +7603,8 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
}
}
if (themingActive) OpenThemeData(hwnd, themeClass);
return 0;
fail:
@ -7584,6 +7618,24 @@ fail:
return -1;
}
/***
* DESCRIPTION:
* Destroys the listview control.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
*
* RETURN:
* Success: 0
* Failure: -1
*/
static LRESULT LISTVIEW_Destroy(LISTVIEW_INFO *infoPtr)
{
HTHEME theme = GetWindowTheme(infoPtr->hwndSelf);
CloseThemeData(theme);
return 0;
}
/***
* DESCRIPTION:
* Enables the listview control.
@ -8274,10 +8326,15 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE
switch (lpnmh->hdr.code)
{
case HDN_TRACKW:
case HDN_TRACKA:
case HDN_ITEMCHANGINGW:
case HDN_ITEMCHANGINGA:
return notify_forward_header(infoPtr, lpnmh);
case HDN_ITEMCHANGEDW:
case HDN_ITEMCHANGEDA:
notify_forward_header(infoPtr, lpnmh);
/* Fall through */
case HDN_TRACKW:
case HDN_TRACKA:
{
COLUMN_INFO *lpColumnInfo;
INT dx, cxy;
@ -8347,6 +8404,53 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE
return 0;
}
/***
* DESCRIPTION:
* Paint non-client area of control.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structureof the sender
* [I] region : update region
*
* RETURN:
* TRUE - frame was painted
* FALSE - call default window proc
*/
static BOOL LISTVIEW_NCPaint(LISTVIEW_INFO *infoPtr, HRGN region)
{
HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
BOOL themingActive = IsAppThemed() && IsThemeActive();
BOOL doTheming = themingActive && (theme != NULL);
HDC dc;
RECT r;
HRGN cliprgn;
int cxEdge = GetSystemMetrics (SM_CXEDGE),
cyEdge = GetSystemMetrics (SM_CYEDGE);
if (!doTheming) return FALSE;
GetWindowRect(infoPtr->hwndSelf, &r);
cliprgn = CreateRectRgn (r.left + cxEdge, r.top + cyEdge,
r.right - cxEdge, r.bottom - cyEdge);
if (region != (HRGN)1)
CombineRgn (cliprgn, cliprgn, region, RGN_AND);
OffsetRect(&r, -r.left, -r.top);
dc = GetDCEx(infoPtr->hwndSelf, region, DCX_WINDOW|DCX_INTERSECTRGN);
OffsetRect(&r, -r.left, -r.top);
if (IsThemeBackgroundPartiallyTransparent (theme, 0, 0))
DrawThemeParentBackground(infoPtr->hwndSelf, dc, &r);
DrawThemeBackground (theme, dc, 0, 0, &r, 0);
ReleaseDC(infoPtr->hwndSelf, dc);
/* Call default proc to get the scrollbars etc. painted */
DefWindowProcW (infoPtr->hwndSelf, WM_NCPAINT, (WPARAM)cliprgn, 0);
return TRUE;
}
/***
* DESCRIPTION:
* Determines the type of structure to use.
@ -9244,6 +9348,9 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_CREATE:
return LISTVIEW_Create(hwnd, (LPCREATESTRUCTW)lParam);
case WM_DESTROY:
return LISTVIEW_Destroy(infoPtr);
case WM_ENABLE:
return LISTVIEW_Enable(infoPtr, (BOOL)wParam);
@ -9283,6 +9390,11 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_NCDESTROY:
return LISTVIEW_NCDestroy(infoPtr);
case WM_NCPAINT:
if (LISTVIEW_NCPaint(infoPtr, (HRGN)wParam))
return 0;
goto fwd_msg;
case WM_NOTIFY:
if (lParam && ((LPNMHDR)lParam)->hwndFrom == infoPtr->hwndHeader)
return LISTVIEW_HeaderNotification(infoPtr, (LPNMHEADERW)lParam);
@ -9331,6 +9443,8 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return 0;
/* case WM_TIMER: */
case WM_THEMECHANGED:
return LISTVIEW_ThemeChanged(infoPtr);
case WM_VSCROLL:
return LISTVIEW_VScroll(infoPtr, (INT)LOWORD(wParam), 0, (HWND)lParam);

View file

@ -33,7 +33,6 @@
* - Enforcing of minimal wizard size
* - Messages:
* o PSM_GETRESULT
* o PSM_IDTOINDEX
* o PSM_INSERTPAGE
* o PSM_RECALCPAGESIZES
* o PSM_SETHEADERSUBTITLE
@ -45,7 +44,6 @@
* o PSN_QUERYINITIALFOCUS
* o PSN_TRANSLATEACCELERATOR
* - Styles:
* o PSH_WIZARDHASFINISH
* o PSH_RTLREADING
* o PSH_STRETCHWATERMARK
* o PSH_USEPAGELANG
@ -68,6 +66,7 @@
#include "commctrl.h"
#include "prsht.h"
#include "comctl32.h"
#include "uxtheme.h"
#include "wine/debug.h"
#include "wine/unicode.h"
@ -121,6 +120,7 @@ typedef struct tagPropSheetInfo
BOOL isModeless;
BOOL hasHelp;
BOOL hasApply;
BOOL hasFinish;
BOOL useCallback;
BOOL restartWindows;
BOOL rebootSystem;
@ -233,13 +233,11 @@ static VOID PROPSHEET_UnImplementedFlags(DWORD dwFlags)
/*
* unhandled header flags:
* PSH_WIZARDHASFINISH 0x00000010
* PSH_RTLREADING 0x00000800
* PSH_STRETCHWATERMARK 0x00040000
* PSH_USEPAGELANG 0x00200000
*/
add_flag(PSH_WIZARDHASFINISH);
add_flag(PSH_RTLREADING);
add_flag(PSH_STRETCHWATERMARK);
add_flag(PSH_USEPAGELANG);
@ -341,6 +339,7 @@ static BOOL PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh,
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;
@ -396,6 +395,7 @@ static BOOL PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh,
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;
@ -1004,6 +1004,8 @@ static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent,
if (psInfo->hasHelp)
num_buttons++;
if (psInfo->hasFinish)
num_buttons++;
/*
* Obtain the size of the buttons.
@ -1024,40 +1026,47 @@ static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent,
* All buttons will be at this y coordinate.
*/
y = rcSheet.bottom - (padding.y + buttonHeight);
/*
* Position the Next and the Finish buttons.
*/
hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON);
x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1));
SetWindowPos(hwndButton, 0, x, y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON);
SetWindowPos(hwndButton, 0, x, y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
ShowWindow(hwndButton, SW_HIDE);
/*
* Position the Back button.
*/
hwndButton = GetDlgItem(hwndParent, IDC_BACK_BUTTON);
x -= buttonWidth;
x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1)) - buttonWidth;
SetWindowPos(hwndButton, 0, x, y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
/*
* Position the Next button.
*/
hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON);
x += buttonWidth;
SetWindowPos(hwndButton, 0, x, y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
/*
* Position the Finish button.
*/
hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON);
if (psInfo->hasFinish)
x += padding.x + buttonWidth;
SetWindowPos(hwndButton, 0, x, y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
if (!psInfo->hasFinish)
ShowWindow(hwndButton, SW_HIDE);
/*
* Position the Cancel button.
*/
hwndButton = GetDlgItem(hwndParent, IDCANCEL);
x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 2));
x += padding.x + buttonWidth;
SetWindowPos(hwndButton, 0, x, y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
@ -1069,7 +1078,7 @@ static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent,
if (psInfo->hasHelp)
{
x = rcSheet.right - (padding.x + buttonWidth);
x += padding.x + buttonWidth;
SetWindowPos(hwndButton, 0, x, y, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
@ -1533,6 +1542,8 @@ static BOOL PROPSHEET_CreatePage(HWND hwndParent,
SetWindowSubclass(hwndPage, PROPSHEET_WizardSubclassProc, 1,
(DWORD_PTR)ppshpage);
}
if (!(psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD))
EnableThemeDialogTexture (hwndPage, ETDT_ENABLETAB);
return TRUE;
}
@ -1623,9 +1634,6 @@ static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo)
ShowWindow(hwndLineHeader, SW_SHOW);
}
InvalidateRgn(hwndDlg, NULL, TRUE);
UpdateWindow(hwndDlg);
return TRUE;
}
@ -2196,6 +2204,7 @@ static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText)
*/
static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
{
PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr);
HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
TRACE("'%s'\n", lpszText);
@ -2211,9 +2220,12 @@ static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
ShowWindow(hwndButton, SW_HIDE);
/* Hide Next button */
hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
ShowWindow(hwndButton, SW_HIDE);
if (!psInfo->hasFinish)
{
/* Hide Next button */
hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
ShowWindow(hwndButton, SW_HIDE);
}
}
/******************************************************************************
@ -2221,6 +2233,7 @@ static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText)
*/
static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText)
{
PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr);
HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
TRACE("'%s'\n", debugstr_w(lpszText));
@ -2236,9 +2249,12 @@ static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText)
hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
ShowWindow(hwndButton, SW_HIDE);
/* Hide Next button */
hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
ShowWindow(hwndButton, SW_HIDE);
if (!psInfo->hasFinish)
{
/* Hide Next button */
hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
ShowWindow(hwndButton, SW_HIDE);
}
}
/******************************************************************************
@ -2439,6 +2455,8 @@ static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
*/
static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
{
PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg,
PropSheetInfoStr);
HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON);
HWND hwndNext = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON);
HWND hwndFinish = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON);
@ -2454,8 +2472,11 @@ static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
if (dwFlags & PSWIZB_NEXT)
{
/* Hide the Finish button */
ShowWindow(hwndFinish, SW_HIDE);
if (!psInfo->hasFinish)
{
/* Hide the Finish button */
ShowWindow(hwndFinish, SW_HIDE);
}
/* Show and enable the Next button */
ShowWindow(hwndNext, SW_SHOW);
@ -2465,20 +2486,27 @@ static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags)
SendMessageW(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0);
}
if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH))
if (!psInfo->hasFinish)
{
/* Hide the Next button */
ShowWindow(hwndNext, SW_HIDE);
if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH))
{
/* Hide the Next button */
ShowWindow(hwndNext, SW_HIDE);
/* Show the Finish button */
ShowWindow(hwndFinish, SW_SHOW);
/* Show the Finish button */
ShowWindow(hwndFinish, SW_SHOW);
if (!(dwFlags & PSWIZB_DISABLEDFINISH))
{
EnableWindow(hwndFinish, TRUE);
if (dwFlags & PSWIZB_FINISH)
EnableWindow(hwndFinish, TRUE);
/* Set the Finish button as the default pushbutton */
SendMessageW(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
/* Set the Finish button as the default pushbutton */
SendMessageW(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0);
}
}
}
else if (!(dwFlags & PSWIZB_DISABLEDFINISH))
EnableWindow(hwndFinish, TRUE);
}
/******************************************************************************
@ -2596,7 +2624,17 @@ static LRESULT PROPSHEET_IndexToPage(HWND hwndDlg, int iPageIndex)
*/
static LRESULT PROPSHEET_IdToIndex(HWND hwndDlg, int iPageId)
{
FIXME("(%p, %d): stub\n", hwndDlg, iPageId);
int index;
LPCPROPSHEETPAGEW psp;
PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg,
PropSheetInfoStr);
TRACE("(%p, %d)\n", hwndDlg, iPageId);
for (index = 0; index < psInfo->nPages; index++) {
psp = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage;
if (psp->u.pszTemplate == (LPCWSTR)iPageId)
return index;
}
return -1;
}
@ -3473,6 +3511,10 @@ PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return FALSE;
}
case WM_SYSCOLORCHANGE:
COMCTL32_RefreshSysColors();
return FALSE;
case PSM_GETCURRENTPAGEHWND:
{

View file

@ -118,7 +118,6 @@ typedef struct
typedef struct
{
DWORD dwStructSize; /* size of TBBUTTON struct */
INT nHeight; /* height of the toolbar */
INT nWidth; /* width of the toolbar */
RECT client_rect;
RECT rcBound; /* bounding rectangle */
@ -156,8 +155,6 @@ typedef struct
HWND hwndToolTip; /* handle to tool tip control */
HWND hwndNotify; /* handle to the window that gets notifications */
HWND hwndSelf; /* my own handle */
BOOL bBtnTranspnt; /* button transparency flag */
BOOL bAutoSize; /* auto size deadlock indicator */
BOOL bAnchor; /* anchor highlight enabled */
BOOL bDoRedraw; /* Redraw status */
BOOL bDragOutSent; /* has TBN_DRAGOUT notification been sent for this drag? */
@ -249,6 +246,7 @@ static VOID TOOLBAR_DeleteImageList(PIMLENTRY **pies, INT *cies);
static HIMAGELIST TOOLBAR_InsertImageList(PIMLENTRY **pies, INT *cies, HIMAGELIST himl, INT id);
static LRESULT TOOLBAR_LButtonDown(HWND hwnd, WPARAM wParam, LPARAM lParam);
static void TOOLBAR_SetHotItemEx (TOOLBAR_INFO *infoPtr, INT nHit, DWORD dwReason);
static LRESULT TOOLBAR_AutoSize(HWND hwnd);
static LRESULT
TOOLBAR_NotifyFormat(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam);
@ -580,7 +578,7 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, RECT *rcText, LPWSTR lpText,
else if ((state & CDIS_MARKED) && !(infoPtr->dwItemCDFlag & TBCDRF_NOMARK)) {
clrOld = SetTextColor (hdc, tbcd->clrTextHighlight);
clrOldBk = SetBkColor (hdc, tbcd->clrMark);
oldBkMode = SetBkMode (hdc, OPAQUE); /* FIXME: should this be in the NMTBCUSTOMDRAW structure? */
oldBkMode = SetBkMode (hdc, tbcd->nHLStringBkMode);
}
else {
clrOld = SetTextColor (hdc, tbcd->clrText);
@ -671,7 +669,7 @@ TOOLBAR_TranslateState(TBUTTON_INFO *btnPtr)
retstate |= (btnPtr->fsState & TBSTATE_ENABLED) ? 0 : CDIS_DISABLED;
retstate |= (btnPtr->fsState & TBSTATE_MARKED ) ? CDIS_MARKED : 0;
retstate |= (btnPtr->bHot ) ? CDIS_HOT : 0;
retstate |= (btnPtr->fsState & TBSTATE_INDETERMINATE) ? CDIS_INDETERMINATE : 0;
retstate |= ((btnPtr->fsState & (TBSTATE_ENABLED|TBSTATE_INDETERMINATE)) == (TBSTATE_ENABLED|TBSTATE_INDETERMINATE)) ? CDIS_INDETERMINATE : 0;
/* NOTE: we don't set CDIS_GRAYED, CDIS_FOCUS, CDIS_DEFAULT */
return retstate;
}
@ -815,6 +813,7 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
NMTBCUSTOMDRAW tbcd;
DWORD ntfret;
INT offset;
INT oldBkMode;
rc = btnPtr->rect;
CopyRect (&rcArrow, &rc);
@ -894,8 +893,8 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
tbcd.clrBtnHighlight = comctl32_color.clrBtnHighlight;
tbcd.clrMark = comctl32_color.clrHighlight;
tbcd.clrHighlightHotTrack = 0;
tbcd.nStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE;
tbcd.nHLStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE;
tbcd.nStringBkMode = TRANSPARENT;
tbcd.nHLStringBkMode = OPAQUE;
/* MSDN says that this is the text rectangle.
* But (why always a but) tracing of v5.7 of native shows
* that this is really a *relative* rectangle based on the
@ -983,8 +982,10 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
if (drawSepDropDownArrow)
TOOLBAR_DrawSepDDArrow(infoPtr, &tbcd, &rcArrow, btnPtr->bDropDownPressed);
oldBkMode = SetBkMode (hdc, tbcd.nStringBkMode);
if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT))
TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd);
SetBkMode (hdc, oldBkMode);
TOOLBAR_DrawImage(infoPtr, btnPtr, rcBitmap.left, rcBitmap.top, &tbcd);
@ -1007,16 +1008,8 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc)
FINALNOTIFY:
if (infoPtr->dwItemCustDraw & CDRF_NOTIFYPOSTPAINT)
{
tbcd.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
tbcd.nmcd.hdc = hdc;
tbcd.nmcd.rc = rc;
tbcd.nmcd.dwItemSpec = btnPtr->idCommand;
tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr);
tbcd.nmcd.lItemlParam = btnPtr->dwData;
tbcd.rcText = rcText;
tbcd.nStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE;
tbcd.nHLStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE;
ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
tbcd.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
}
}
@ -1027,7 +1020,7 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
{
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
TBUTTON_INFO *btnPtr;
INT i, oldBKmode = 0;
INT i;
RECT rcTemp, rcClient;
NMTBCUSTOMDRAW tbcd;
DWORD ntfret;
@ -1055,9 +1048,6 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
infoPtr->dwBaseCustDraw = ntfret & 0xffff;
if (infoPtr->bBtnTranspnt)
oldBKmode = SetBkMode (hdc, TRANSPARENT);
GetClientRect(hwnd, &rcClient);
/* redraw necessary buttons */
@ -1092,9 +1082,6 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps)
COMCTL32_DrawInsertMark(hdc, &rcInsertMark, infoPtr->clrInsertMark, FALSE);
}
if (infoPtr->bBtnTranspnt && (oldBKmode != TRANSPARENT))
SetBkMode (hdc, oldBKmode);
if (infoPtr->dwBaseCustDraw & CDRF_NOTIFYPOSTPAINT)
{
ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
@ -1175,12 +1162,20 @@ TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize)
lpSize->cx = 0;
lpSize->cy = 0;
if(infoPtr->nMaxTextRows == 0)
if (infoPtr->nMaxTextRows == 0)
return;
hdc = GetDC (hwnd);
hOldFont = SelectObject (hdc, infoPtr->hFont);
if (infoPtr->nNumButtons == 0)
{
TEXTMETRICW tm;
GetTextMetricsW(hdc, &tm);
lpSize->cy = tm.tmHeight;
}
btnPtr = infoPtr->buttons;
for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
if(TOOLBAR_HasText(infoPtr, btnPtr))
@ -1557,7 +1552,6 @@ TOOLBAR_CalcToolbar (HWND hwnd)
INT x, y, cx, cy;
SIZE sizeString, sizeButton;
BOOL bWrap;
BOOL usesBitmaps = FALSE;
BOOL validImageList = FALSE;
BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
@ -1565,14 +1559,9 @@ TOOLBAR_CalcToolbar (HWND hwnd)
TOOLBAR_DumpToolbar (infoPtr, __LINE__);
for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++)
{
if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap))
usesBitmaps = TRUE;
}
if (TOOLBAR_IsValidImageList(infoPtr, 0))
validImageList = TRUE;
sizeButton = TOOLBAR_MeasureButton(infoPtr, sizeString, usesBitmaps, validImageList);
sizeButton = TOOLBAR_MeasureButton(infoPtr, sizeString, TRUE, validImageList);
infoPtr->nButtonWidth = sizeButton.cx;
infoPtr->nButtonHeight = sizeButton.cy;
@ -1584,14 +1573,14 @@ TOOLBAR_CalcToolbar (HWND hwnd)
TOOLBAR_WrapToolbar( hwnd, dwStyle );
x = infoPtr->nIndent;
y = 0;
if (infoPtr->dwStyle & TBSTYLE_FLAT)
y = 0;
else
y = TOP_BORDER;
/* from above, minimum is a button, and possible text */
cx = infoPtr->nButtonWidth;
infoPtr->nHeight = infoPtr->nButtonHeight;
cy = infoPtr->nHeight;
cy = infoPtr->nButtonHeight;
nRows = nSepRows = 0;
@ -1613,7 +1602,7 @@ TOOLBAR_CalcToolbar (HWND hwnd)
continue;
}
cy = infoPtr->nHeight;
cy = infoPtr->nButtonHeight;
/* UNDOCUMENTED: If a separator has a non zero bitmap index, */
/* it is the actual width of the separator. This is used for */
@ -1728,27 +1717,7 @@ TOOLBAR_CalcToolbar (HWND hwnd)
/* infoPtr->nRows is the number of rows on the toolbar */
infoPtr->nRows = nRows + nSepRows + 1;
#if 0
/********************************************************************
* The following while interesting, does not match the values *
* created above for the button rectangles, nor the rcBound rect. *
* We will comment it out and remove it later. *
* *
* The problem showed up as heights in the pager control that was *
* wrong. *
********************************************************************/
/* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */
/* the last row. */
infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight +
nSepRows * (SEPARATOR_WIDTH * 2 / 3) +
nSepRows * (infoPtr->nBitmapHeight + 1) +
BOTTOM_BORDER;
#endif
infoPtr->nHeight = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth);
TRACE("toolbar button width %d\n", infoPtr->nButtonWidth);
}
@ -2731,7 +2700,7 @@ TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
TBITMAP_INFO *oldBitmaps = infoPtr->bitmaps;
infoPtr->bitmaps = Alloc((infoPtr->nNumBitmapInfos + 1) * sizeof(TBITMAP_INFO));
memcpy(&infoPtr->bitmaps[0], &oldBitmaps[0], infoPtr->nNumBitmapInfos);
memcpy(&infoPtr->bitmaps[0], &oldBitmaps[0], infoPtr->nNumBitmapInfos * sizeof(TBITMAP_INFO));
}
infoPtr->bitmaps[infoPtr->nNumBitmapInfos].nButtons = nButtons;
@ -2821,6 +2790,7 @@ TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam)
}
TOOLBAR_CalcToolbar (hwnd);
TOOLBAR_AutoSize (hwnd);
TOOLBAR_DumpToolbar (infoPtr, __LINE__);
@ -2889,6 +2859,7 @@ TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam)
}
TOOLBAR_CalcToolbar (hwnd);
TOOLBAR_AutoSize (hwnd);
TOOLBAR_DumpToolbar (infoPtr, __LINE__);
@ -3082,66 +3053,66 @@ TOOLBAR_AutoSize (HWND hwnd)
{
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
RECT parent_rect;
RECT window_rect;
HWND parent;
INT x, y;
INT cx, cy;
UINT uPosFlags = SWP_NOZORDER;
TRACE("resize forced, style=%lx!\n", infoPtr->dwStyle);
TRACE("auto sizing, style=%lx!\n", infoPtr->dwStyle);
parent = GetParent (hwnd);
if (!parent || !infoPtr->bDoRedraw)
return 0;
GetClientRect(parent, &parent_rect);
x = parent_rect.left;
y = parent_rect.top;
/* FIXME: we should be able to early out if nothing */
/* has changed with nWidth != parent_rect width */
TRACE("nRows: %d, infoPtr->nButtonHeight: %d\n", infoPtr->nRows, infoPtr->nButtonHeight);
if (infoPtr->dwStyle & CCS_NORESIZE) {
uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
cx = 0;
cy = 0;
TOOLBAR_CalcToolbar (hwnd);
cy = TOP_BORDER + infoPtr->nRows * infoPtr->nButtonHeight + BOTTOM_BORDER;
cx = parent_rect.right - parent_rect.left;
if ((infoPtr->dwStyle & TBSTYLE_WRAPABLE) || (infoPtr->dwExStyle & TBSTYLE_EX_UNDOC1))
{
TOOLBAR_CalcToolbar(hwnd);
InvalidateRect( hwnd, NULL, TRUE );
}
else {
infoPtr->nWidth = parent_rect.right - parent_rect.left;
TOOLBAR_CalcToolbar (hwnd);
InvalidateRect( hwnd, NULL, TRUE );
cy = infoPtr->nHeight;
cx = infoPtr->nWidth;
if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_NOMOVEY) {
GetWindowRect(hwnd, &window_rect);
ScreenToClient(parent, (LPPOINT)&window_rect.left);
y = window_rect.top;
}
if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_BOTTOM) {
if (!(infoPtr->dwStyle & CCS_NORESIZE))
{
RECT window_rect;
UINT uPosFlags = SWP_NOZORDER;
if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_NOMOVEY)
{
GetWindowRect(hwnd, &window_rect);
ScreenToClient(parent, (LPPOINT)&window_rect.left);
y = window_rect.top;
}
if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_BOTTOM)
{
GetWindowRect(hwnd, &window_rect);
y = parent_rect.bottom - ( window_rect.bottom - window_rect.top);
}
if (infoPtr->dwStyle & CCS_NOPARENTALIGN)
uPosFlags |= SWP_NOMOVE;
if (!(infoPtr->dwStyle & CCS_NODIVIDER))
cy += GetSystemMetrics(SM_CYEDGE);
if (infoPtr->dwStyle & WS_BORDER)
{
x = y = 1; /* FIXME: this looks wrong */
cy += GetSystemMetrics(SM_CYEDGE);
cx += GetSystemMetrics(SM_CXEDGE);
}
SetWindowPos(hwnd, NULL, x, y, cx, cy, uPosFlags);
}
if (infoPtr->dwStyle & CCS_NOPARENTALIGN)
uPosFlags |= SWP_NOMOVE;
if (!(infoPtr->dwStyle & CCS_NODIVIDER))
cy += GetSystemMetrics(SM_CYEDGE);
if (infoPtr->dwStyle & WS_BORDER)
{
x = y = 1;
cy += GetSystemMetrics(SM_CYEDGE);
cx += GetSystemMetrics(SM_CXEDGE);
}
infoPtr->bAutoSize = TRUE;
SetWindowPos (hwnd, HWND_TOP, x, y, cx, cy, uPosFlags);
/* The following line makes sure that the infoPtr->bAutoSize is turned off
* after the setwindowpos calls */
infoPtr->bAutoSize = FALSE;
return 0;
}
@ -3985,6 +3956,7 @@ TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam)
Free (oldButtons);
TOOLBAR_CalcToolbar (hwnd);
TOOLBAR_AutoSize (hwnd);
InvalidateRect (hwnd, NULL, TRUE);
@ -4085,6 +4057,7 @@ TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam)
Free (oldButtons);
TOOLBAR_CalcToolbar (hwnd);
TOOLBAR_AutoSize (hwnd);
InvalidateRect (hwnd, NULL, TRUE);
@ -4330,6 +4303,7 @@ TOOLBAR_MoveButton (HWND hwnd, WPARAM wParam, LPARAM lParam)
}
TOOLBAR_CalcToolbar(hwnd);
TOOLBAR_AutoSize(hwnd);
InvalidateRect(hwnd, NULL, TRUE);
return TRUE;
@ -4369,6 +4343,7 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
LPTBREPLACEBITMAP lpReplace = (LPTBREPLACEBITMAP) lParam;
HBITMAP hBitmap;
HBITMAP hbmLoad = NULL;
int i = 0, nOldButtons = 0, pos = 0;
int nOldBitmaps, nNewBitmaps = 0;
HIMAGELIST himlDef = 0;
@ -4383,9 +4358,12 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
return FALSE;
}
else if (lpReplace->hInstOld != 0)
{
FIXME("resources not in the current module not implemented\n");
return FALSE;
if (lpReplace->hInstNew)
{
hbmLoad = LoadBitmapW(lpReplace->hInstNew,(LPWSTR)lpReplace->nIDNew);
hBitmap = hbmLoad;
}
else
{
@ -4412,6 +4390,8 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
if (nOldButtons == 0)
{
WARN("No hinst/bitmap found! hInst %p nID %x\n", lpReplace->hInstOld, lpReplace->nIDOld);
if (hbmLoad)
DeleteObject (hbmLoad);
return FALSE;
}
@ -4463,6 +4443,8 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam)
InvalidateRect(hwnd, NULL, TRUE);
if (hbmLoad)
DeleteObject (hbmLoad);
return TRUE;
}
@ -4864,12 +4846,6 @@ TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam)
infoPtr->cxMin = (INT)LOWORD(lParam);
infoPtr->cxMax = (INT)HIWORD(lParam);
/* if both values are 0 then we are done */
if (lParam == 0) {
TRACE("setting both min and max to 0, norecalc\n");
return TRUE;
}
/* otherwise we need to recalc the toolbar and in some cases
recalc the bounding rectangle (does DrawText w/ DT_CALCRECT
which doesn't actually draw - GA). */
@ -5530,7 +5506,6 @@ TOOLBAR_Unkwn463 (HWND hwnd, WPARAM wParam, LPARAM lParam)
break;
case 1:
lpsize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
/* lpsize->cy = infoPtr->nHeight; */
break;
default:
ERR("Unknown wParam %d for Toolbar message [0463]. Please report\n",
@ -5566,7 +5541,6 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
infoPtr->nBitmapHeight = 15;
infoPtr->nBitmapWidth = 16;
infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER;
infoPtr->nMaxTextRows = 1;
infoPtr->cxMin = -1;
infoPtr->cxMax = -1;
@ -5579,7 +5553,6 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
infoPtr->nOldHit = -1;
infoPtr->nHotItem = -1;
infoPtr->hwndNotify = ((LPCREATESTRUCTW)lParam)->hwndParent;
infoPtr->bBtnTranspnt = (dwStyle & (TBSTYLE_FLAT | TBSTYLE_LIST));
infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS: DT_CENTER | DT_END_ELLIPSIS;
infoPtr->bAnchor = FALSE; /* no anchor highlighting */
infoPtr->bDragOutSent = FALSE;
@ -6641,131 +6614,50 @@ static LRESULT
TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
{
TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
DWORD dwStyle = infoPtr->dwStyle;
RECT parent_rect;
RECT window_rect;
HWND parent;
INT x, y;
INT cx, cy;
INT flags;
UINT uPosFlags = 0;
/* Resize deadlock check */
if (infoPtr->bAutoSize) {
infoPtr->bAutoSize = FALSE;
return 0;
}
/* FIXME: optimize to only update size if the new size doesn't */
/* match the current size */
flags = (INT) wParam;
/* FIXME for flags =
* SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED
*/
TRACE("sizing toolbar!\n");
if (flags == SIZE_RESTORED) {
/* width and height don't apply */
parent = GetParent (hwnd);
GetClientRect(parent, &parent_rect);
x = parent_rect.left;
y = parent_rect.top;
if (infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS)
{
RECT delta_width, delta_height, client, dummy;
DWORD min_x, max_x, min_y, max_y;
TBUTTON_INFO *btnPtr;
INT i;
if (dwStyle & CCS_NORESIZE) {
uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE);
/*
* this sets the working width of the toolbar, and
* Calc Toolbar will not adjust it, only the height
*/
infoPtr->nWidth = parent_rect.right - parent_rect.left;
cy = infoPtr->nHeight;
cx = infoPtr->nWidth;
TOOLBAR_CalcToolbar (hwnd);
infoPtr->nWidth = cx;
infoPtr->nHeight = cy;
}
else {
infoPtr->nWidth = parent_rect.right - parent_rect.left;
TOOLBAR_CalcToolbar (hwnd);
cy = infoPtr->nHeight;
cx = infoPtr->nWidth;
if ((dwStyle & CCS_BOTTOM) == CCS_NOMOVEY) {
GetWindowRect(hwnd, &window_rect);
ScreenToClient(parent, (LPPOINT)&window_rect.left);
y = window_rect.top;
}
if ((dwStyle & CCS_BOTTOM) == CCS_BOTTOM) {
GetWindowRect(hwnd, &window_rect);
y = parent_rect.bottom -
( window_rect.bottom - window_rect.top);
}
}
if (dwStyle & CCS_NOPARENTALIGN) {
uPosFlags |= SWP_NOMOVE;
cy = infoPtr->nHeight;
cx = infoPtr->nWidth;
}
if (!(dwStyle & CCS_NODIVIDER))
cy += GetSystemMetrics(SM_CYEDGE);
if (dwStyle & WS_BORDER)
{
x = y = 1;
cy += GetSystemMetrics(SM_CYEDGE);
cx += GetSystemMetrics(SM_CXEDGE);
}
if(infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS)
GetClientRect(hwnd, &client);
if(client.right > infoPtr->client_rect.right)
{
RECT delta_width, delta_height, client, dummy;
DWORD min_x, max_x, min_y, max_y;
TBUTTON_INFO *btnPtr;
INT i;
GetClientRect(hwnd, &client);
if(client.right > infoPtr->client_rect.right)
{
min_x = infoPtr->client_rect.right;
max_x = client.right;
}
else
{
max_x = infoPtr->client_rect.right;
min_x = client.right;
}
if(client.bottom > infoPtr->client_rect.bottom)
{
min_y = infoPtr->client_rect.bottom;
max_y = client.bottom;
}
else
{
max_y = infoPtr->client_rect.bottom;
min_y = client.bottom;
}
SetRect(&delta_width, min_x, 0, max_x, min_y);
SetRect(&delta_height, 0, min_y, max_x, max_y);
TRACE("delta_width %s delta_height %s\n", wine_dbgstr_rect(&delta_width), wine_dbgstr_rect(&delta_height));
btnPtr = infoPtr->buttons;
for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
if(IntersectRect(&dummy, &delta_width, &btnPtr->rect) ||
IntersectRect(&dummy, &delta_height, &btnPtr->rect))
InvalidateRect(hwnd, &btnPtr->rect, TRUE);
min_x = infoPtr->client_rect.right;
max_x = client.right;
}
else
{
max_x = infoPtr->client_rect.right;
min_x = client.right;
}
if(client.bottom > infoPtr->client_rect.bottom)
{
min_y = infoPtr->client_rect.bottom;
max_y = client.bottom;
}
else
{
max_y = infoPtr->client_rect.bottom;
min_y = client.bottom;
}
if((uPosFlags & (SWP_NOSIZE | SWP_NOMOVE)) != (SWP_NOSIZE | SWP_NOMOVE))
SetWindowPos (hwnd, 0, x, y, cx, cy, uPosFlags | SWP_NOZORDER);
SetRect(&delta_width, min_x, 0, max_x, min_y);
SetRect(&delta_height, 0, min_y, max_x, max_y);
TRACE("delta_width %s delta_height %s\n", wine_dbgstr_rect(&delta_width), wine_dbgstr_rect(&delta_height));
btnPtr = infoPtr->buttons;
for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
if(IntersectRect(&dummy, &delta_width, &btnPtr->rect) ||
IntersectRect(&dummy, &delta_height, &btnPtr->rect))
InvalidateRect(hwnd, &btnPtr->rect, TRUE);
}
GetClientRect(hwnd, &infoPtr->client_rect);
TOOLBAR_AutoSize(hwnd);
return 0;
}
@ -6782,8 +6674,6 @@ TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle)
else
infoPtr->dwDTFlags = DT_CENTER | DT_END_ELLIPSIS;
infoPtr->bBtnTranspnt = (lpStyle->styleNew &
(TBSTYLE_FLAT | TBSTYLE_LIST));
TOOLBAR_CheckStyle (hwnd, lpStyle->styleNew);
TRACE("new style 0x%08lx\n", lpStyle->styleNew);

View file

@ -40,6 +40,8 @@
#include "winnls.h"
#include "commctrl.h"
#include "comctl32.h"
#include "uxtheme.h"
#include "tmschema.h"
#include "wine/unicode.h"
#include "wine/debug.h"
@ -75,7 +77,8 @@ typedef struct
#define DEFAULT_ADDBOT 0 /* amount to extend below the buddy window */
#define DEFAULT_BUDDYBORDER 2 /* Width/height of the buddy border */
#define DEFAULT_BUDDYSPACER 2 /* Spacer between the buddy and the ctrl */
#define DEFAULT_BUDDYBORDER_THEMED 1 /* buddy border when theming is enabled */
#define DEFAULT_BUDDYSPACER_THEMED 0 /* buddy spacer when theming is enabled */
/* Work constants */
@ -175,6 +178,9 @@ static BOOL UPDOWN_HasBuddyBorder(UPDOWN_INFO* infoPtr)
*/
static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow)
{
HTHEME theme = GetWindowTheme (infoPtr->Self);
const int border = theme ? DEFAULT_BUDDYBORDER_THEMED : DEFAULT_BUDDYBORDER;
const int spacer = theme ? DEFAULT_BUDDYSPACER_THEMED : DEFAULT_BUDDYSPACER;
GetClientRect (infoPtr->Self, rect);
/*
@ -183,17 +189,17 @@ static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow)
*/
if (UPDOWN_HasBuddyBorder(infoPtr)) {
if (infoPtr->dwStyle & UDS_ALIGNLEFT)
rect->left += DEFAULT_BUDDYBORDER;
rect->left += border;
else
rect->right -= DEFAULT_BUDDYBORDER;
rect->right -= border;
InflateRect(rect, 0, -DEFAULT_BUDDYBORDER);
InflateRect(rect, 0, -border);
}
/* now figure out if we need a space away from the buddy */
if ( IsWindow(infoPtr->Buddy) ) {
if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= DEFAULT_BUDDYSPACER;
else rect->left += DEFAULT_BUDDYSPACER;
if (IsWindow(infoPtr->Buddy) ) {
if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= spacer;
else rect->left += spacer;
}
/*
@ -206,11 +212,11 @@ static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow)
if (arrow & FLAG_INCR)
rect->left = rect->left + len/2;
if (arrow & FLAG_DECR)
rect->right = rect->left + len/2 - 1;
rect->right = rect->left + len/2 - (theme ? 0 : 1);
} else {
int len = rect->bottom - rect->top + 1; /* compute the height */
if (arrow & FLAG_INCR)
rect->bottom = rect->top + len/2 - 1;
rect->bottom = rect->top + len/2 - (theme ? 0 : 1);
if (arrow & FLAG_DECR)
rect->top = rect->top + len/2;
}
@ -219,10 +225,10 @@ static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow)
/***********************************************************************
* UPDOWN_GetArrowFromPoint
* Returns the rectagle (for the up or down arrow) that contains pt.
* If it returns the up rect, it returns TRUE.
* If it returns the down rect, it returns FALSE.
* If it returns the up rect, it returns FLAG_INCR.
* If it returns the down rect, it returns FLAG_DECR.
*/
static BOOL UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt)
static INT UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt)
{
UPDOWN_GetArrowRect (infoPtr, rect, FLAG_INCR);
if(PtInRect(rect, pt)) return FLAG_INCR;
@ -341,6 +347,24 @@ static BOOL UPDOWN_SetBuddyInt (UPDOWN_INFO *infoPtr)
return SetWindowTextW(infoPtr->Buddy, txt);
}
/***********************************************************************
* UPDOWN_DrawBuddyBackground
*
* Draw buddy background for visual integration.
*/
static BOOL UPDOWN_DrawBuddyBackground (UPDOWN_INFO *infoPtr, HDC hdc)
{
RECT br;
HTHEME buddyTheme = GetWindowTheme (infoPtr->Buddy);
if (!buddyTheme) return FALSE;
GetClientRect (infoPtr->Buddy, &br);
MapWindowPoints (infoPtr->Buddy, infoPtr->Self, (POINT*)&br, 2);
/* FIXME: take disabled etc. into account */
DrawThemeBackground (buddyTheme, hdc, 0, 0, &br, NULL);
return TRUE;
}
/***********************************************************************
* UPDOWN_Draw
*
@ -348,36 +372,61 @@ static BOOL UPDOWN_SetBuddyInt (UPDOWN_INFO *infoPtr)
*/
static LRESULT UPDOWN_Draw (UPDOWN_INFO *infoPtr, HDC hdc)
{
BOOL pressed, hot;
BOOL uPressed, uHot, dPressed, dHot;
RECT rect;
HTHEME theme = GetWindowTheme (infoPtr->Self);
int uPart = 0, uState = 0, dPart = 0, dState = 0;
BOOL needBuddyBg = FALSE;
uPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR);
uHot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
dPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR);
dHot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
if (theme) {
uPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_UPHORZ : SPNP_UP;
uState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED
: (uPressed ? DNS_PRESSED : (uHot ? DNS_HOT : DNS_NORMAL));
dPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_DOWNHORZ : SPNP_DOWN;
dState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED
: (dPressed ? DNS_PRESSED : (dHot ? DNS_HOT : DNS_NORMAL));
needBuddyBg = IsWindow (infoPtr->Buddy)
&& (IsThemeBackgroundPartiallyTransparent (theme, uPart, uState)
|| IsThemeBackgroundPartiallyTransparent (theme, dPart, dState));
}
/* Draw the common border between ourselves and our buddy */
if (UPDOWN_HasBuddyBorder(infoPtr)) {
GetClientRect(infoPtr->Self, &rect);
DrawEdge(hdc, &rect, EDGE_SUNKEN,
BF_BOTTOM | BF_TOP |
(infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT));
if (UPDOWN_HasBuddyBorder(infoPtr) || needBuddyBg) {
if (!theme || !UPDOWN_DrawBuddyBackground (infoPtr, hdc)) {
GetClientRect(infoPtr->Self, &rect);
DrawEdge(hdc, &rect, EDGE_SUNKEN,
BF_BOTTOM | BF_TOP |
(infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT));
}
}
/* Draw the incr button */
UPDOWN_GetArrowRect (infoPtr, &rect, FLAG_INCR);
pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR);
hot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
DrawFrameControl(hdc, &rect, DFC_SCROLL,
(infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) |
((infoPtr->dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) |
(pressed ? DFCS_PUSHED : 0) |
(infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
if (theme) {
DrawThemeBackground(theme, hdc, uPart, uState, &rect, NULL);
} else {
DrawFrameControl(hdc, &rect, DFC_SCROLL,
(infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) |
((infoPtr->dwStyle & UDS_HOTTRACK) && uHot ? DFCS_HOT : 0) |
(uPressed ? DFCS_PUSHED : 0) |
(infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
}
/* Draw the decr button */
UPDOWN_GetArrowRect(infoPtr, &rect, FLAG_DECR);
pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR);
hot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
DrawFrameControl(hdc, &rect, DFC_SCROLL,
(infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) |
((infoPtr->dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) |
(pressed ? DFCS_PUSHED : 0) |
(infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
if (theme) {
DrawThemeBackground(theme, hdc, dPart, dState, &rect, NULL);
} else {
DrawFrameControl(hdc, &rect, DFC_SCROLL,
(infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) |
((infoPtr->dwStyle & UDS_HOTTRACK) && dHot ? DFCS_HOT : 0) |
(dPressed ? DFCS_PUSHED : 0) |
(infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
}
return 0;
}
@ -653,6 +702,7 @@ static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, INT x, INT
POINT pt = { x, y };
RECT rect;
int temp, arrow;
TRACKMOUSEEVENT tme;
TRACE("msg %04x point %s\n", msg, wine_dbgstr_point(&pt));
@ -713,7 +763,19 @@ static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, INT x, INT
/* If state changed, redraw the control */
if(temp != infoPtr->Flags)
InvalidateRect (infoPtr->Self, &rect, FALSE);
InvalidateRect (infoPtr->Self, NULL, FALSE);
/* Set up tracking so the mousein flags can be reset when the
* mouse leaves the control */
tme.cbSize = sizeof( tme );
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = infoPtr->Self;
TrackMouseEvent (&tme);
break;
case WM_MOUSELEAVE:
infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW);
InvalidateRect (infoPtr->Self, NULL, FALSE);
break;
default:
@ -729,6 +791,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L
{
UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr (hwnd);
int temp;
static const WCHAR themeClass[] = {'S','p','i','n',0};
HTHEME theme;
TRACE("hwnd=%p msg=%04x wparam=%08x lparam=%08lx\n", hwnd, message, wParam, lParam);
@ -761,6 +825,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L
if (infoPtr->dwStyle & UDS_AUTOBUDDY)
UPDOWN_SetBuddy (infoPtr, GetWindow (hwnd, GW_HWNDPREV));
OpenThemeData (hwnd, themeClass);
TRACE("UpDown Ctrl creation, hwnd=%p\n", hwnd);
break;
@ -771,6 +837,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L
Free (infoPtr);
SetWindowLongPtrW (hwnd, 0, 0);
theme = GetWindowTheme (hwnd);
CloseThemeData (theme);
TRACE("UpDown Ctrl destruction, hwnd=%p\n", hwnd);
break;
@ -791,6 +859,13 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L
}
break;
case WM_THEMECHANGED:
theme = GetWindowTheme (hwnd);
CloseThemeData (theme);
OpenThemeData (hwnd, themeClass);
InvalidateRect (hwnd, NULL, FALSE);
break;
case WM_TIMER:
/* is this the auto-press timer? */
if(wParam == TIMER_AUTOPRESS) {
@ -849,6 +924,7 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L
case WM_LBUTTONDOWN:
case WM_MOUSEMOVE:
case WM_MOUSELEAVE:
if(UPDOWN_IsEnabled(infoPtr))
UPDOWN_HandleMouseEvent (infoPtr, message, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
break;