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