1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/nativdlg.cpp
3 // Purpose:     Native dialog loading code (part of wxWindow)
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     04/01/98
7 // RCS-ID:      $Id: nativdlg.cpp 39720 2006-06-14 15:55:43Z VZ $
8 // Copyright:   (c) Julian Smart
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15 
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19 
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22 
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26 
27 #ifndef WX_PRECOMP
28     #include <stdio.h>
29 
30     #include "wx/wx.h"
31 #endif
32 
33 #include "wx/spinbutt.h"
34 #include "wx/msw/private.h"
35 
36 // ---------------------------------------------------------------------------
37 // global functions
38 // ---------------------------------------------------------------------------
39 
40 extern LONG APIENTRY _EXPORT wxDlgProc(HWND hWnd, UINT message,
41                                        WPARAM wParam, LPARAM lParam);
42 
43 // ===========================================================================
44 // implementation
45 // ===========================================================================
46 
LoadNativeDialog(wxWindow * parent,wxWindowID & id)47 bool wxWindow::LoadNativeDialog(wxWindow* parent, wxWindowID& id)
48 {
49     m_windowId = id;
50 
51     wxWindowCreationHook hook(this);
52     m_hWnd = (WXHWND)::CreateDialog((HINSTANCE)wxGetInstance(),
53                                     MAKEINTRESOURCE(id),
54                                     parent ? (HWND)parent->GetHWND() : 0,
55                                     (DLGPROC) wxDlgProc);
56 
57     if ( !m_hWnd )
58         return false;
59 
60     SubclassWin(GetHWND());
61 
62     if ( parent )
63         parent->AddChild(this);
64     else
65         wxTopLevelWindows.Append(this);
66 
67     // Enumerate all children
68     HWND hWndNext;
69     hWndNext = ::GetWindow((HWND) m_hWnd, GW_CHILD);
70 
71     if (hWndNext)
72         CreateWindowFromHWND(this, (WXHWND) hWndNext);
73 
74     while (hWndNext != (HWND) NULL)
75     {
76         hWndNext = ::GetWindow(hWndNext, GW_HWNDNEXT);
77         if (hWndNext)
78             CreateWindowFromHWND(this, (WXHWND) hWndNext);
79     }
80 
81     return true;
82 }
83 
LoadNativeDialog(wxWindow * parent,const wxString & name)84 bool wxWindow::LoadNativeDialog(wxWindow* parent, const wxString& name)
85 {
86     SetName(name);
87 
88     wxWindowCreationHook hook(this);
89     m_hWnd = (WXHWND)::CreateDialog((HINSTANCE) wxGetInstance(),
90                                     name.c_str(),
91                                     parent ? (HWND)parent->GetHWND() : 0,
92                                     (DLGPROC)wxDlgProc);
93 
94     if ( !m_hWnd )
95         return false;
96 
97     SubclassWin(GetHWND());
98 
99     if ( parent )
100         parent->AddChild(this);
101     else
102         wxTopLevelWindows.Append(this);
103 
104     // Enumerate all children
105     HWND hWndNext;
106     hWndNext = ::GetWindow((HWND) m_hWnd, GW_CHILD);
107 
108     if (hWndNext)
109         CreateWindowFromHWND(this, (WXHWND) hWndNext);
110 
111     while (hWndNext != (HWND) NULL)
112     {
113         hWndNext = ::GetWindow(hWndNext, GW_HWNDNEXT);
114         if (hWndNext)
115             CreateWindowFromHWND(this, (WXHWND) hWndNext);
116     }
117 
118     return true;
119 }
120 
121 // ---------------------------------------------------------------------------
122 // look for child by id
123 // ---------------------------------------------------------------------------
124 
GetWindowChild1(wxWindowID id)125 wxWindow* wxWindow::GetWindowChild1(wxWindowID id)
126 {
127     if ( m_windowId == id )
128         return this;
129 
130     wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
131     while ( node )
132     {
133         wxWindow* child = node->GetData();
134         wxWindow* win = child->GetWindowChild1(id);
135         if ( win )
136             return win;
137 
138         node = node->GetNext();
139     }
140 
141     return NULL;
142 }
143 
GetWindowChild(wxWindowID id)144 wxWindow* wxWindow::GetWindowChild(wxWindowID id)
145 {
146     wxWindow* win = GetWindowChild1(id);
147     if ( !win )
148     {
149         HWND hwnd = ::GetDlgItem(GetHwnd(), id);
150         if ( hwnd )
151         {
152             win = CreateWindowFromHWND(this, (WXHWND) hwnd);
153         }
154     }
155 
156     return win;
157 }
158 
159 // ---------------------------------------------------------------------------
160 // create wxWin window from a native HWND
161 // ---------------------------------------------------------------------------
162 
CreateWindowFromHWND(wxWindow * parent,WXHWND hWnd)163 wxWindow* wxWindow::CreateWindowFromHWND(wxWindow* parent, WXHWND hWnd)
164 {
165     wxString str(wxGetWindowClass(hWnd));
166     str.UpperCase();
167 
168     long id = wxGetWindowId(hWnd);
169     long style = GetWindowLong((HWND) hWnd, GWL_STYLE);
170 
171     wxWindow* win = NULL;
172 
173     if (str == wxT("BUTTON"))
174     {
175         int style1 = (style & 0xFF);
176 #if wxUSE_CHECKBOX
177         if ((style1 == BS_3STATE) || (style1 == BS_AUTO3STATE) || (style1 == BS_AUTOCHECKBOX) ||
178             (style1 == BS_CHECKBOX))
179         {
180             win = new wxCheckBox;
181         }
182         else
183 #endif
184 #if wxUSE_RADIOBTN
185         if ((style1 == BS_AUTORADIOBUTTON) || (style1 == BS_RADIOBUTTON))
186         {
187             win = new wxRadioButton;
188         }
189         else
190 #endif
191 #if wxUSE_BMPBUTTON
192 #if defined(__WIN32__) && defined(BS_BITMAP)
193         if (style & BS_BITMAP)
194         {
195             // TODO: how to find the bitmap?
196             win = new wxBitmapButton;
197             wxLogError(wxT("Have not yet implemented bitmap button as BS_BITMAP button."));
198         }
199         else
200 #endif
201         if (style1 == BS_OWNERDRAW)
202         {
203             // TODO: how to find the bitmap?
204             // TODO: can't distinguish between bitmap button and bitmap static.
205             // Change implementation of wxStaticBitmap to SS_BITMAP.
206             // PROBLEM: this assumes that we're using resource-based bitmaps.
207             // So maybe need 2 implementations of bitmap buttons/static controls,
208             // with a switch in the drawing code. Call default proc if BS_BITMAP.
209             win = new wxBitmapButton;
210         }
211         else
212 #endif
213 #if wxUSE_BUTTON
214         if ((style1 == BS_PUSHBUTTON) || (style1 == BS_DEFPUSHBUTTON))
215         {
216             win = new wxButton;
217         }
218         else
219 #endif
220 #if wxUSE_STATBOX
221         if (style1 == BS_GROUPBOX)
222         {
223             win = new wxStaticBox;
224         }
225         else
226 #endif
227         {
228             wxLogError(wxT("Don't know what kind of button this is: id = %ld"),
229                        id);
230         }
231     }
232 #if wxUSE_COMBOBOX
233     else if (str == wxT("COMBOBOX"))
234     {
235         win = new wxComboBox;
236     }
237 #endif
238 #if wxUSE_TEXTCTRL
239     // TODO: Problem if the user creates a multiline - but not rich text - text control,
240     // since wxWin assumes RichEdit control for this. Should have m_isRichText in
241     // wxTextCtrl. Also, convert as much of the window style as is necessary
242     // for correct functioning.
243     // Could have wxWindow::AdoptAttributesFromHWND(WXHWND)
244     // to be overridden by each control class.
245     else if (str == wxT("EDIT"))
246     {
247         win = new wxTextCtrl;
248     }
249 #endif
250 #if wxUSE_LISTBOX
251     else if (str == wxT("LISTBOX"))
252     {
253         win = new wxListBox;
254     }
255 #endif
256 #if wxUSE_SCROLLBAR
257     else if (str == wxT("SCROLLBAR"))
258     {
259         win = new wxScrollBar;
260     }
261 #endif
262 #if wxUSE_SPINBTN
263     else if (str == wxT("MSCTLS_UPDOWN32"))
264     {
265         win = new wxSpinButton;
266     }
267 #endif
268 #if wxUSE_SLIDER
269     else if (str == wxT("MSCTLS_TRACKBAR32"))
270     {
271         // Need to ascertain if it's horiz or vert
272         win = new wxSlider;
273     }
274 #endif // wxUSE_SLIDER
275 #if wxUSE_STATTEXT
276     else if (str == wxT("STATIC"))
277     {
278         int style1 = (style & 0xFF);
279 
280         if ((style1 == SS_LEFT) || (style1 == SS_RIGHT)
281 #ifndef __WXWINCE__
282             || (style1 == SS_SIMPLE)
283 #endif
284             )
285             win = new wxStaticText;
286 #if wxUSE_STATBMP
287 #if defined(__WIN32__) && defined(BS_BITMAP)
288         else if (style1 == SS_BITMAP)
289         {
290             win = new wxStaticBitmap;
291 
292             // Help! this doesn't correspond with the wxWin implementation.
293             wxLogError(wxT("Please make SS_BITMAP statics into owner-draw buttons."));
294         }
295 #endif
296 #endif /* wxUSE_STATBMP */
297     }
298 #endif
299     else
300     {
301         wxString msg(wxT("Don't know how to convert from Windows class "));
302         msg += str;
303         wxLogError(msg);
304     }
305 
306     if (win)
307     {
308         parent->AddChild(win);
309         win->SetEventHandler(win);
310         win->SetHWND(hWnd);
311         win->SetId(id);
312         win->SubclassWin(hWnd);
313         win->AdoptAttributesFromHWND();
314         win->SetupColours();
315     }
316 
317     return win;
318 }
319 
320 // Make sure the window style (etc.) reflects the HWND style (roughly)
AdoptAttributesFromHWND(void)321 void wxWindow::AdoptAttributesFromHWND(void)
322 {
323     HWND hWnd = (HWND) GetHWND();
324     long style = GetWindowLong((HWND) hWnd, GWL_STYLE);
325 
326     if (style & WS_VSCROLL)
327         m_windowStyle |= wxVSCROLL;
328     if (style & WS_HSCROLL)
329         m_windowStyle |= wxHSCROLL;
330 }
331