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