1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/colordlg.cpp
3 // Purpose:     wxColourDialog class
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     01/02/97
7 // Copyright:   (c) Julian Smart
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #if wxUSE_COLOURDLG && !(defined(__SMARTPHONE__) && defined(__WXWINCE__))
27 
28 #include "wx/colordlg.h"
29 #include "wx/modalhook.h"
30 
31 #ifndef WX_PRECOMP
32     #include "wx/msw/wrapcdlg.h"
33     #include <stdio.h>
34     #include "wx/colour.h"
35     #include "wx/gdicmn.h"
36     #include "wx/utils.h"
37     #include "wx/math.h"
38 #endif
39 
40 #include "wx/msw/private.h"
41 
42 #include <stdlib.h>
43 #include <string.h>
44 
45 // ----------------------------------------------------------------------------
46 // globals
47 // ----------------------------------------------------------------------------
48 
49 // standard colors dialog size for the Windows systems
50 // this is ok if color dialog created with standart color
51 // and "Define Custom Colors" extension not shown
52 static wxRect gs_rectDialog(0, 0, 222, 324);
53 
54 // ----------------------------------------------------------------------------
55 // wxWin macros
56 // ----------------------------------------------------------------------------
57 
IMPLEMENT_DYNAMIC_CLASS(wxColourDialog,wxDialog)58 IMPLEMENT_DYNAMIC_CLASS(wxColourDialog, wxDialog)
59 
60 // ============================================================================
61 // implementation
62 // ============================================================================
63 
64 // ----------------------------------------------------------------------------
65 // colour dialog hook proc
66 // ----------------------------------------------------------------------------
67 
68 UINT_PTR CALLBACK
69 wxColourDialogHookProc(HWND hwnd,
70                        UINT uiMsg,
71                        WPARAM WXUNUSED(wParam),
72                        LPARAM lParam)
73 {
74     if ( uiMsg == WM_INITDIALOG )
75     {
76         CHOOSECOLOR *pCC = (CHOOSECOLOR *)lParam;
77         wxColourDialog * const
78             dialog = reinterpret_cast<wxColourDialog *>(pCC->lCustData);
79 
80         const wxString title = dialog->GetTitle();
81         if ( !title.empty() )
82             ::SetWindowText(hwnd, title.t_str());
83 
84         dialog->MSWOnInitDone((WXHWND)hwnd);
85     }
86 
87     return 0;
88 }
89 
90 // ----------------------------------------------------------------------------
91 // wxColourDialog
92 // ----------------------------------------------------------------------------
93 
Init()94 void wxColourDialog::Init()
95 {
96     m_movedWindow = false;
97     m_centreDir = 0;
98 
99     // reset to zero, otherwise the wx routines won't size the window the
100     // second time the dialog is shown, because they would believe it already
101     // has the requested size/position
102     gs_rectDialog.x =
103     gs_rectDialog.y = 0;
104 }
105 
Create(wxWindow * parent,wxColourData * data)106 bool wxColourDialog::Create(wxWindow *parent, wxColourData *data)
107 {
108     m_parent = parent;
109     if (data)
110         m_colourData = *data;
111 
112     return true;
113 }
114 
ShowModal()115 int wxColourDialog::ShowModal()
116 {
117     WX_HOOK_MODAL_DIALOG();
118 
119     // initialize the struct used by Windows
120     CHOOSECOLOR chooseColorStruct;
121     memset(&chooseColorStruct, 0, sizeof(CHOOSECOLOR));
122 
123     size_t i;
124 
125     // and transfer data from m_colourData to it
126     COLORREF custColours[16];
127     for ( i = 0; i < WXSIZEOF(custColours); i++ )
128     {
129         if ( m_colourData.GetCustomColour(i).IsOk() )
130             custColours[i] = wxColourToRGB(m_colourData.GetCustomColour(i));
131         else
132             custColours[i] = RGB(255,255,255);
133     }
134 
135     chooseColorStruct.lStructSize = sizeof(CHOOSECOLOR);
136     if ( m_parent )
137         chooseColorStruct.hwndOwner = GetHwndOf(m_parent);
138     chooseColorStruct.rgbResult = wxColourToRGB(m_colourData.GetColour());
139     chooseColorStruct.lpCustColors = custColours;
140 
141     chooseColorStruct.Flags = CC_RGBINIT | CC_ENABLEHOOK;
142     chooseColorStruct.lCustData = (LPARAM)this;
143     chooseColorStruct.lpfnHook = wxColourDialogHookProc;
144 
145     if ( m_colourData.GetChooseFull() )
146         chooseColorStruct.Flags |= CC_FULLOPEN;
147 
148     // do show the modal dialog
149     if ( !::ChooseColor(&chooseColorStruct) )
150     {
151         // 0 error means the dialog was simply cancelled, i.e. no real error
152         // occurred
153         const DWORD err = CommDlgExtendedError();
154         if ( err )
155         {
156             wxLogError(_("Colour selection dialog failed with error %0lx."), err);
157         }
158 
159         return wxID_CANCEL;
160     }
161 
162 
163     // transfer the values chosen by user back into m_colourData
164     for ( i = 0; i < WXSIZEOF(custColours); i++ )
165     {
166       wxRGBToColour(m_colourData.m_custColours[i], custColours[i]);
167     }
168 
169     wxRGBToColour(m_colourData.GetColour(), chooseColorStruct.rgbResult);
170 
171     // this doesn't seem to work (contrary to what MSDN implies) on current
172     // Windows versions: CC_FULLOPEN is never set on return if it wasn't
173     // initially set and vice versa
174     //m_colourData.SetChooseFull((chooseColorStruct.Flags & CC_FULLOPEN) != 0);
175 
176     return wxID_OK;
177 }
178 
179 // ----------------------------------------------------------------------------
180 // title
181 // ----------------------------------------------------------------------------
182 
SetTitle(const wxString & title)183 void wxColourDialog::SetTitle(const wxString& title)
184 {
185     m_title = title;
186 }
187 
GetTitle() const188 wxString wxColourDialog::GetTitle() const
189 {
190     return m_title;
191 }
192 
193 // ----------------------------------------------------------------------------
194 // position/size
195 // ----------------------------------------------------------------------------
196 
DoGetPosition(int * x,int * y) const197 void wxColourDialog::DoGetPosition(int *x, int *y) const
198 {
199     if ( x )
200         *x = gs_rectDialog.x;
201     if ( y )
202         *y = gs_rectDialog.y;
203 }
204 
DoCentre(int dir)205 void wxColourDialog::DoCentre(int dir)
206 {
207     m_centreDir = dir;
208 
209     // it's unnecessary to do anything else at this stage as we'll redo it in
210     // MSWOnInitDone() anyhow
211 }
212 
DoMoveWindow(int x,int y,int WXUNUSED (w),int WXUNUSED (h))213 void wxColourDialog::DoMoveWindow(int x, int y, int WXUNUSED(w), int WXUNUSED(h))
214 {
215     gs_rectDialog.x = x;
216     gs_rectDialog.y = y;
217 
218     // our HWND is only set when we're called from MSWOnInitDone(), test if
219     // this is the case
220     HWND hwnd = GetHwnd();
221     if ( hwnd )
222     {
223         // size of the dialog can't be changed because the controls are not
224         // laid out correctly then
225        ::SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
226     }
227     else // just remember that we were requested to move the window
228     {
229         m_movedWindow = true;
230 
231         // if Centre() had been called before, it shouldn't be taken into
232         // account now
233         m_centreDir = 0;
234     }
235 }
236 
DoGetSize(int * width,int * height) const237 void wxColourDialog::DoGetSize(int *width, int *height) const
238 {
239     if ( width )
240         *width = gs_rectDialog.width;
241     if ( height )
242         *height = gs_rectDialog.height;
243 }
244 
DoGetClientSize(int * width,int * height) const245 void wxColourDialog::DoGetClientSize(int *width, int *height) const
246 {
247     if ( width )
248         *width = gs_rectDialog.width;
249     if ( height )
250         *height = gs_rectDialog.height;
251 }
252 
MSWOnInitDone(WXHWND hDlg)253 void wxColourDialog::MSWOnInitDone(WXHWND hDlg)
254 {
255     // set HWND so that our DoMoveWindow() works correctly
256     SetHWND(hDlg);
257 
258     if ( m_centreDir )
259     {
260         // now we have the real dialog size, remember it
261         RECT rect;
262         ::GetWindowRect((HWND)hDlg, &rect);
263         gs_rectDialog = wxRectFromRECT(rect);
264 
265         // and position the window correctly: notice that we must use the base
266         // class version as our own doesn't do anything except setting flags
267         wxDialog::DoCentre(m_centreDir);
268     }
269     else if ( m_movedWindow ) // need to just move it to the correct place
270     {
271         SetPosition(GetPosition());
272     }
273 
274     // we shouldn't destroy hDlg, so disassociate from it
275     SetHWND(NULL);
276 }
277 
278 #endif // wxUSE_COLOURDLG && !(__SMARTPHONE__ && __WXWINCE__)
279