ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

theme_combo.c
Go to the documentation of this file.
00001 /*
00002  * Theming - Combo box control
00003  *
00004  * Copyright (c) 2005 by Frank Richter
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  */
00021 
00022 #include <stdarg.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "wingdi.h"
00029 #include "winuser.h"
00030 #include "uxtheme.h"
00031 #include "vssym32.h"
00032 #include "comctl32.h"
00033 #include "wine/debug.h"
00034 
00035 WINE_DEFAULT_DEBUG_CHANNEL(themingcombo);
00036 
00037 /* Subclass-private state flags */
00038 #define STATE_NOREDRAW         1
00039 #define STATE_HOT              2
00040 
00041 /* some constants for metrics, same as in user32 */
00042 #define COMBO_XBORDERSIZE      2
00043 #define COMBO_YBORDERSIZE      2
00044 #define COMBO_EDITBUTTONSPACE  0
00045 #define EDIT_CONTROL_PADDING   1
00046 
00047 /* paint text of combobox, needed for read-only drop downs. */
00048 static void paint_text (HWND hwnd, HDC hdc, DWORD dwStyle, const COMBOBOXINFO *cbi)
00049 {
00050     INT  id, size = 0;
00051     LPWSTR pText = NULL;
00052     UINT itemState = ODS_COMBOBOXEDIT;
00053     HFONT font = (HFONT)SendMessageW (hwnd, WM_GETFONT, 0, 0);
00054     HFONT hPrevFont = (font) ? SelectObject(hdc, font) : 0;
00055     RECT rectEdit;
00056     BOOL focused = GetFocus () == hwnd;
00057     BOOL dropped = cbi->stateButton == STATE_SYSTEM_PRESSED;
00058 
00059     TRACE("\n");
00060 
00061     /* follow Windows combobox that sends a bunch of text
00062      * inquiries to its listbox while processing WM_PAINT. */
00063 
00064     if( (id = SendMessageW (cbi->hwndList, LB_GETCURSEL, 0, 0) ) != LB_ERR )
00065     {
00066         size = SendMessageW (cbi->hwndList, LB_GETTEXTLEN, id, 0);
00067         if (size == LB_ERR)
00068           FIXME("LB_ERR probably not handled yet\n");
00069         if( (pText = HeapAlloc( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR))) )
00070         {
00071             /* size from LB_GETTEXTLEN may be too large, from LB_GETTEXT is accurate */
00072             size = SendMessageW (cbi->hwndList, LB_GETTEXT, id, (LPARAM)pText);
00073             pText[size] = '\0'; /* just in case */
00074         } else return;
00075     }
00076     else
00077        if( !(dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) )
00078            return;
00079 
00080     /*
00081      * Give ourselves some space.
00082      */
00083     CopyRect (&rectEdit, &cbi->rcItem);
00084     InflateRect( &rectEdit, -1, -1 );
00085      
00086     if(dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))
00087     {
00088        DRAWITEMSTRUCT dis;
00089        HRGN           clipRegion;
00090        UINT ctlid = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID );
00091 
00092        /* setup state for DRAWITEM message. Owner will highlight */
00093        if ( focused && !dropped )
00094            itemState |= ODS_SELECTED | ODS_FOCUS;
00095 
00096        /*
00097         * Save the current clip region.
00098         * To retrieve the clip region, we need to create one "dummy"
00099         * clip region.
00100         */
00101        clipRegion = CreateRectRgnIndirect(&rectEdit);
00102 
00103        if (GetClipRgn(hdc, clipRegion)!=1)
00104        {
00105          DeleteObject(clipRegion);
00106          clipRegion=NULL;
00107        }
00108 
00109        if (!IsWindowEnabled(hwnd)) itemState |= ODS_DISABLED;
00110 
00111        dis.CtlType      = ODT_COMBOBOX;
00112        dis.CtlID        = ctlid;
00113        dis.hwndItem     = hwnd;
00114        dis.itemAction   = ODA_DRAWENTIRE;
00115        dis.itemID       = id;
00116        dis.itemState    = itemState;
00117        dis.hDC          = hdc;
00118        dis.rcItem       = rectEdit;
00119        dis.itemData     = SendMessageW(cbi->hwndList, LB_GETITEMDATA, id, 0);
00120 
00121        /*
00122         * Clip the DC and have the parent draw the item.
00123         */
00124        IntersectClipRect(hdc,
00125                          rectEdit.left,  rectEdit.top,
00126                          rectEdit.right, rectEdit.bottom);
00127 
00128        SendMessageW(GetParent (hwnd), WM_DRAWITEM, ctlid, (LPARAM)&dis );
00129 
00130        /*
00131         * Reset the clipping region.
00132         */
00133        SelectClipRgn(hdc, clipRegion);
00134     }
00135     else
00136     {
00137        static const WCHAR empty_stringW[] = { 0 };
00138 
00139        if ( focused && !dropped ) {
00140 
00141            /* highlight */
00142            FillRect( hdc, &rectEdit, GetSysColorBrush(COLOR_HIGHLIGHT) );
00143            SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
00144            SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
00145       }
00146 
00147       ExtTextOutW( hdc,
00148                    rectEdit.left + 1,
00149                    rectEdit.top + 1,
00150                    ETO_OPAQUE | ETO_CLIPPED,
00151                    &rectEdit,
00152                    pText ? pText : empty_stringW , size, NULL );
00153 
00154       if ( focused && !dropped )
00155         DrawFocusRect( hdc, &rectEdit );
00156     }
00157 
00158     if( hPrevFont )
00159       SelectObject(hdc, hPrevFont );
00160    
00161     HeapFree( GetProcessHeap(), 0, pText );
00162 }
00163 
00164 /* paint the combobox */
00165 static LRESULT paint (HTHEME theme, HWND hwnd, HDC hParamDC, ULONG state)
00166 {
00167   PAINTSTRUCT ps;
00168   HDC   hDC;
00169   COMBOBOXINFO cbi;
00170   DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
00171 
00172   hDC = (hParamDC) ? hParamDC
00173                    : BeginPaint( hwnd, &ps);
00174 
00175   TRACE("hdc=%p\n", hDC);
00176 
00177   if( hDC && !(state & STATE_NOREDRAW) )
00178   {
00179       RECT frameRect;
00180       int buttonState;
00181   
00182       cbi.cbSize = sizeof (cbi);
00183       SendMessageW (hwnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)&cbi);
00184       
00185       /* paint border */
00186       if ((dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE)
00187           GetClientRect (hwnd, &frameRect);
00188       else
00189       {
00190           CopyRect (&frameRect, &cbi.rcItem);
00191 
00192           InflateRect(&frameRect, 
00193               EDIT_CONTROL_PADDING + COMBO_XBORDERSIZE, 
00194               EDIT_CONTROL_PADDING + COMBO_YBORDERSIZE);
00195       }
00196       
00197       DrawThemeBackground (theme, hDC, 0, 
00198           IsWindowEnabled (hwnd) ? CBXS_NORMAL : CBXS_DISABLED, &frameRect, NULL);
00199       
00200       /* paint button */
00201       if (cbi.stateButton != STATE_SYSTEM_INVISIBLE)
00202       {
00203           if (!IsWindowEnabled (hwnd))
00204               buttonState = CBXS_DISABLED;
00205           else if (cbi.stateButton == STATE_SYSTEM_PRESSED)
00206               buttonState = CBXS_PRESSED;
00207           else if (state & STATE_HOT)
00208               buttonState = CBXS_HOT;
00209           else
00210               buttonState = CBXS_NORMAL;
00211           DrawThemeBackground (theme, hDC, CP_DROPDOWNBUTTON, buttonState, 
00212               &cbi.rcButton, NULL);
00213       }
00214 
00215       /* paint text, if we need to */
00216       if ((dwStyle & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST)
00217           paint_text (hwnd, hDC, dwStyle, &cbi);
00218   }
00219 
00220   if( !hParamDC )
00221     EndPaint(hwnd, &ps);
00222 
00223   return 0;
00224 }
00225 
00226 
00227 /**********************************************************************
00228  * The combo control subclass window proc.
00229  */
00230 LRESULT CALLBACK THEMING_ComboSubclassProc (HWND hwnd, UINT msg, 
00231                                             WPARAM wParam, LPARAM lParam, 
00232                                             ULONG_PTR dwRefData)
00233 {
00234     const WCHAR* themeClass = WC_COMBOBOXW;
00235     HTHEME theme;
00236     LRESULT result;
00237       
00238     switch (msg)
00239     {
00240     case WM_CREATE:
00241         result = THEMING_CallOriginalClass  (hwnd, msg, wParam, lParam);
00242         OpenThemeData( hwnd, themeClass );
00243         return result;
00244     
00245     case WM_DESTROY:
00246         theme = GetWindowTheme( hwnd );
00247         CloseThemeData ( theme );
00248         return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam);
00249 
00250     case WM_THEMECHANGED:
00251         theme = GetWindowTheme( hwnd );
00252         CloseThemeData ( theme );
00253         OpenThemeData( hwnd, themeClass );
00254         break;
00255         
00256     case WM_SYSCOLORCHANGE:
00257         theme = GetWindowTheme( hwnd );
00258     if (!theme) return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam);
00259         /* Do nothing. When themed, a WM_THEMECHANGED will be received, too,
00260      * which will do the repaint. */
00261         break;
00262         
00263     case WM_PAINT:
00264         theme = GetWindowTheme( hwnd );
00265         if (!theme) return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam);
00266         return paint (theme, hwnd, (HDC)wParam, dwRefData);
00267 
00268     case WM_SETREDRAW:
00269         /* Since there doesn't seem to be WM_GETREDRAW, do redraw tracking in 
00270          * the subclass as well. */
00271         if( wParam )
00272             dwRefData &= ~STATE_NOREDRAW;
00273         else
00274             dwRefData |= STATE_NOREDRAW;
00275         THEMING_SetSubclassData (hwnd, dwRefData);
00276         return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam);
00277         
00278     case WM_MOUSEMOVE:
00279         {
00280             /* Dropdown button hot-tracking */
00281             COMBOBOXINFO cbi;
00282             POINT pt;
00283 
00284             pt.x = (short)LOWORD(lParam);
00285             pt.y = (short)HIWORD(lParam);
00286             cbi.cbSize = sizeof (cbi);
00287             SendMessageW (hwnd, CB_GETCOMBOBOXINFO, 0, (LPARAM)&cbi);
00288             
00289             if (cbi.stateButton != STATE_SYSTEM_INVISIBLE)
00290             {
00291                 if (PtInRect (&cbi.rcButton, pt))
00292                 {
00293                     if (!(dwRefData & STATE_HOT))
00294                     {
00295                         dwRefData |= STATE_HOT;
00296                         THEMING_SetSubclassData (hwnd, dwRefData);
00297                         RedrawWindow (hwnd, &cbi.rcButton, 0, 
00298                             RDW_INVALIDATE | RDW_UPDATENOW);
00299                     }
00300                 }
00301                 else
00302                 {
00303                     if (dwRefData & STATE_HOT)
00304                     {
00305                         dwRefData &= ~STATE_HOT;
00306                         THEMING_SetSubclassData (hwnd, dwRefData);
00307                         RedrawWindow (hwnd, &cbi.rcButton, 0, 
00308                             RDW_INVALIDATE | RDW_UPDATENOW);
00309                     }
00310                 }
00311             }
00312         }
00313         return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam);
00314     
00315     default: 
00316     /* Call old proc */
00317     return THEMING_CallOriginalClass (hwnd, msg, wParam, lParam);
00318     }
00319     return 0;
00320 }

Generated on Thu May 24 2012 04:23:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.