source: trunk/src/user32/win32class.cpp@ 2076

Last change on this file since 2076 was 2076, checked in by sandervl, 26 years ago

MDI changes + WM_INITMENU support added + disabled experimental support for CS_PARENTDC style

File size: 17.9 KB
Line 
1/* $Id: win32class.cpp,v 1.10 1999-12-14 19:13:19 sandervl Exp $ */
2/*
3 * Win32 Window Class Managment Code for OS/2
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 *
8 * TODO: Right now all class atoms are global. This must be changed.
9 * TODO: Global atoms of classes with CS_GLOBALCLASS flag are not deleted
10 * Must all be changed if we want to support global app classes
11 * that can be used by other apps. (low priority)
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16#include <os2win.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <stdarg.h>
21#include <assert.h>
22#include <misc.h>
23#include <win32class.h>
24#include <win32wnd.h>
25#include <win\winproc.h>
26
27static fDestroyAll = FALSE;
28
29//******************************************************************************
30//Win32WndClass methods:
31//******************************************************************************
32Win32WndClass::Win32WndClass(WNDCLASSEXA *wndclass, BOOL fUnicode) : GenericObject(&wndclasses, OBJTYPE_CLASS)
33{
34 isUnicode = fUnicode;
35 processId = 0;
36
37 if(HIWORD(wndclass->lpszClassName)) {
38 if(isUnicode) {
39 INT len = lstrlenW((LPWSTR)wndclass->lpszClassName)+1;
40
41 classNameA = (PCHAR)_smalloc(len);
42 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
43 }
44 else {
45 INT len = strlen(wndclass->lpszClassName)+1;
46
47 classNameA = (PCHAR)_smalloc(len);
48 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
49 }
50 if(classNameA == NULL || classNameW == NULL) {
51 dprintf(("Win32Class ctr; classNameA/classNameW == NULL"));
52 exit(1);
53 }
54 if(isUnicode) {
55 lstrcpyW(classNameW, (LPWSTR)wndclass->lpszClassName);
56 UnicodeToAscii(classNameW, classNameA);
57 }
58 else {
59 strcpy((char *)classNameA, wndclass->lpszClassName);
60 AsciiToUnicode(classNameA, classNameW);
61 }
62 classAtom = 0;
63 //SvL: If a system control has already be registered, use that atom instead
64 // of creating a new one
65 if(wndclass->style & CS_GLOBALCLASS) {
66 classAtom = GlobalFindAtomA(classNameA);
67 }
68 if(!classAtom) classAtom = GlobalAddAtomA(classNameA);
69 }
70 else {
71 classNameA = NULL;
72 classNameW = NULL;
73 classAtom = (DWORD)wndclass->lpszClassName;
74 }
75 if(!(wndclass->style & CS_GLOBALCLASS)) {
76 processId = GetCurrentProcess();
77 }
78 menuNameA = 0;
79 menuNameW = 0;
80 setMenuName((LPSTR)wndclass->lpszMenuName);
81
82 dprintf(("USER32: Win32Class ctor\n"));
83 dprintf(("USER32: wndclass->style %X\n", wndclass->style));
84 dprintf(("USER32: wndclass->lpfnWndProc %X\n", wndclass->lpfnWndProc));
85 dprintf(("USER32: wndclass->cbClsExtra %X\n", wndclass->cbClsExtra));
86 dprintf(("USER32: wndclass->cbWndExtra %X\n", wndclass->cbWndExtra));
87 dprintf(("USER32: wndclass->hInstance %X\n", wndclass->hInstance));
88 dprintf(("USER32: wndclass->hIcon %X\n", wndclass->hIcon));
89 dprintf(("USER32: wndclass->hCursor %X\n", wndclass->hCursor));
90 dprintf(("USER32: wndclass->hbrBackground %X\n", wndclass->hbrBackground));
91 if(HIWORD(wndclass->lpszClassName))
92 dprintf(("USER32: wndclass->lpszClassName %s\n", classNameA));
93 else dprintf(("USER32: wndclass->lpszClassName %X\n", wndclass->lpszClassName));
94
95 if(HIWORD(wndclass->lpszMenuName)) {//convert string name identifier to numeric id
96 dprintf(("USER32: lpszMenuName %s\n", menuNameA));
97 }
98 else dprintf(("USER32: wndclass->lpszMenuName %X\n", menuNameA));
99
100 nrExtraClassWords = wndclass->cbClsExtra;
101 nrExtraWindowWords = wndclass->cbWndExtra;
102 backgroundBrush = wndclass->hbrBackground;
103 hCursor = wndclass->hCursor;
104 hIcon = wndclass->hIcon;
105 hInstance = wndclass->hInstance;
106
107 windowStyle = wndclass->style;
108 WINPROC_SetProc((HWINDOWPROC *)&windowProc, wndclass->lpfnWndProc, (isUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS);
109 dprintf2(("Window class ptr %x", windowProc));
110
111 //User data class words/longs
112 if(nrExtraClassWords) {
113 userClassLong = (ULONG *)_smalloc(nrExtraClassWords);
114 if(userClassLong == NULL) {
115 dprintf(("Win32Class ctr: userClassLong == NULL!"));
116 exit(1);
117 }
118 memset(userClassLong, 0, nrExtraClassWords);
119 }
120 else userClassLong = NULL;
121
122 cWindows = 0;
123 hIconSm = wndclass->hIconSm;
124}
125//******************************************************************************
126//******************************************************************************
127Win32WndClass::~Win32WndClass()
128{
129 if(classNameA) {
130 dprintf(("Win32WndClass dtor, destroy class %s\n", classNameA));
131 }
132
133 //SvL: Don't delete global classes
134 if(classNameA && !(windowStyle & CS_GLOBALCLASS)) {
135 GlobalDeleteAtom(classAtom);
136 }
137
138 WINPROC_FreeProc(windowProc, WIN_PROC_CLASS);
139
140 if(userClassLong) free(userClassLong);
141 if(classNameA) free(classNameA);
142 if(classNameW) free(classNameW);
143 if(menuNameA && HIWORD(menuNameA)) {
144 free(menuNameA);
145 assert(menuNameW);
146 free(menuNameW);
147 }
148}
149//******************************************************************************
150//******************************************************************************
151void Win32WndClass::DestroyAll()
152{
153 fDestroyAll = TRUE;
154 GenericObject::DestroyAll(wndclasses);
155}
156//******************************************************************************
157//******************************************************************************
158BOOL Win32WndClass::hasClassName(LPSTR classname, BOOL fUnicode)
159{
160 if(HIWORD(classname) == 0) {
161 return classAtom == (DWORD)classname;
162 }
163 if(fUnicode) {
164 if(classNameW)
165 return (lstrcmpW(classNameW, (LPWSTR)classname) == 0);
166 return FALSE;
167 }
168 else {
169 if(classNameA)
170 return (strcmp(classNameA, classname) == 0);
171 return FALSE;
172 }
173}
174//******************************************************************************
175//******************************************************************************
176Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPSTR id)
177{
178 enterMutex(OBJTYPE_CLASS);
179
180 Win32WndClass *wndclass = (Win32WndClass *)wndclasses;
181
182 if(wndclass == NULL) {
183 leaveMutex(OBJTYPE_CLASS);
184 return(NULL);
185 }
186
187 if(HIWORD(id) != 0) {
188//CB: read comment below!
189 if(lstrcmpiA(wndclass->classNameA, id) == 0 && wndclass->hInstance == hInstance) {
190 leaveMutex(OBJTYPE_CLASS);
191 return(wndclass);
192 }
193 else {
194 wndclass = (Win32WndClass *)wndclass->GetNext();
195 while(wndclass != NULL) {
196 if(lstrcmpiA(wndclass->classNameA, id) == 0)
197 {
198 //SvL: According to Wine, if the instance handle is the one of the main exe, everything is ok
199 if(hInstance == NULL || GetModuleHandleA(NULL) == hInstance ||
200 wndclass->hInstance == hInstance)
201 {
202 leaveMutex(OBJTYPE_CLASS);
203 return(wndclass);
204 }
205 }
206 wndclass = (Win32WndClass *)wndclass->GetNext();
207 }
208 }
209 }
210 else {
211//CB: without HInstance check, test program finds class
212//CB: need more code to compare instance; convert 0 to exe module handle
213 if(wndclass->classAtom == (DWORD)id /*&& wndclass->hInstance == hInstance*/) {
214 leaveMutex(OBJTYPE_CLASS);
215 return(wndclass);
216 }
217 else {
218 wndclass = (Win32WndClass *)wndclass->GetNext();
219 while(wndclass != NULL) {
220 if(wndclass->classAtom == (DWORD)id /* && wndclass->hInstance == hInstance*/) {
221 leaveMutex(OBJTYPE_CLASS);
222 return(wndclass);
223 }
224 wndclass = (Win32WndClass *)wndclass->GetNext();
225 }
226 }
227 }
228 leaveMutex(OBJTYPE_CLASS);
229 dprintf(("Class %X (inst %X) not found!", id, hInstance));
230 return(NULL);
231}
232//******************************************************************************
233//An app can only access another process' class if it's global
234//(all system classes are global)
235//NOTE: NOT USED NOW
236//******************************************************************************
237BOOL Win32WndClass::isAppClass(ULONG curProcessId)
238{
239 if(windowStyle & CS_GLOBALCLASS)
240 return TRUE;
241
242 return curProcessId = processId;
243}
244//******************************************************************************
245//******************************************************************************
246BOOL Win32WndClass::getClassInfo(WNDCLASSEXA *wndclass)
247{
248 wndclass->cbClsExtra = nrExtraClassWords;
249 wndclass->cbWndExtra = nrExtraWindowWords;
250 wndclass->hbrBackground = backgroundBrush;
251 wndclass->hCursor = hCursor;
252 wndclass->hIcon = hIcon;
253 wndclass->hInstance = hInstance;
254 wndclass->lpszMenuName = (LPCTSTR)menuNameA;
255 wndclass->lpszClassName = (classNameA) ? (LPCTSTR)classNameA : (LPCTSTR)classAtom;
256 wndclass->style = windowStyle;
257 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, FALSE);
258 wndclass->hIconSm = hIconSm;
259 return(TRUE);
260}
261//******************************************************************************
262//******************************************************************************
263BOOL Win32WndClass::getClassInfo(WNDCLASSEXW *wndclass)
264{
265 wndclass->cbClsExtra = nrExtraClassWords;
266 wndclass->cbWndExtra = nrExtraWindowWords;
267 wndclass->hbrBackground = backgroundBrush;
268 wndclass->hCursor = hCursor;
269 wndclass->hIcon = hIcon;
270 wndclass->hInstance = hInstance;
271 wndclass->lpszMenuName = (LPCWSTR)menuNameW;
272 wndclass->lpszClassName = (classNameW) ? (LPCWSTR)classNameW : (LPCWSTR)classAtom;
273 wndclass->style = windowStyle;
274 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, TRUE);
275 wndclass->hIconSm = hIconSm;
276 return(TRUE);
277}
278//******************************************************************************
279//******************************************************************************
280ULONG Win32WndClass::getClassName(LPSTR lpszClassName, ULONG cchClassName)
281{
282 if(HIWORD(classNameA)) {
283 lstrcpynA(lpszClassName, classNameA, cchClassName-1);
284 return strlen(lpszClassName);
285 }
286 *(ULONG *)lpszClassName = classAtom;
287 return(sizeof(ULONG));
288}
289//******************************************************************************
290//******************************************************************************
291ULONG Win32WndClass::getClassName(LPWSTR lpszClassName, ULONG cchClassName)
292{
293 ULONG len;
294
295 if(HIWORD(classNameW)) {
296 lstrcpyW(lpszClassName, classNameW);
297 return lstrlenW(lpszClassName)*sizeof(WCHAR);
298 }
299 *(ULONG *)lpszClassName = classAtom;
300 return(sizeof(ULONG));
301}
302//******************************************************************************
303//******************************************************************************
304void Win32WndClass::setMenuName(LPSTR newMenuName)
305{
306 if(HIWORD(menuNameA)) {
307 free(menuNameA);
308 free(menuNameW);
309 menuNameA = 0;
310 menuNameW = 0;
311 }
312 if(HIWORD(newMenuName)) {
313 if(isUnicode) {
314 menuNameA = (PCHAR)_smalloc(lstrlenW((LPWSTR)newMenuName)+1);
315 menuNameW = (WCHAR *)_smalloc((lstrlenW((LPWSTR)newMenuName)+1)*sizeof(WCHAR));
316 }
317 else {
318 menuNameA = (PCHAR)_smalloc(strlen(newMenuName)+1);
319 menuNameW = (WCHAR *)_smalloc((strlen(newMenuName)+1)*sizeof(WCHAR));
320 }
321 if(menuNameA == NULL || menuNameW == NULL) {
322 dprintf(("Win32Class ctr; menuName/menuNameW == NULL"));
323 exit(1);
324 }
325 if(isUnicode) {
326 lstrcpyW(menuNameW, (LPWSTR)newMenuName);
327 UnicodeToAscii(menuNameW, menuNameA);
328 }
329 else {
330 strcpy((char *)menuNameA, newMenuName);
331 AsciiToUnicode(menuNameA, menuNameW);
332 }
333 }
334 else {//id
335 menuNameA = (PCHAR)newMenuName;
336 menuNameW = (WCHAR *)newMenuName;
337 }
338}
339//******************************************************************************
340//******************************************************************************
341ULONG Win32WndClass::getClassLongA(int index, BOOL fUnicode)
342{
343 switch(index) {
344 case GCL_CBCLSEXTRA:
345 return nrExtraClassWords;
346 case GCL_CBWNDEXTRA:
347 return nrExtraWindowWords;
348 case GCL_HBRBACKGROUND:
349 return backgroundBrush;
350 case GCL_HCURSOR:
351 return hCursor;
352 case GCL_HICON:
353 return hIcon;
354 case GCL_HMODULE:
355 return hInstance;
356 case GCL_MENUNAME:
357 return (isUnicode) ? (ULONG)menuNameW : (ULONG)menuNameA;
358 case GCL_STYLE:
359 return windowStyle;
360 case GCL_WNDPROC:
361 return (ULONG) WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
362 case GCW_ATOM: //TODO: does this really happen in windows?
363 SetLastError(ERROR_INVALID_PARAMETER);
364 return 0;
365 default:
366 if(index > 0 && index < nrExtraClassWords - sizeof(ULONG)) {
367 return userClassLong[index];
368 }
369 SetLastError(ERROR_INVALID_PARAMETER);
370 return 0;
371 }
372}
373//******************************************************************************
374//******************************************************************************
375WORD Win32WndClass::getClassWord(int index)
376{
377 switch(index) {
378 case GCW_ATOM:
379 return (WORD)classAtom;
380 default:
381 if(index > 0 && index < nrExtraClassWords - sizeof(WORD)) {
382 return ((WORD *)userClassLong)[index];
383 }
384 SetLastError(ERROR_INVALID_PARAMETER);
385 return 0;
386 }
387}
388//******************************************************************************
389//TODO: What effects what immediately?
390//******************************************************************************
391ULONG Win32WndClass::setClassLongA(int index, LONG lNewVal, BOOL fUnicode)
392{
393 ULONG rc;
394
395 if(classNameA) {
396 dprintf2(("Win32WndClass::setClassLongA %s: %d %x", classNameA, index, lNewVal));
397 }
398 else dprintf2(("Win32WndClass::setClassLongA %d: %d %x", classAtom, index, lNewVal));
399 switch(index) {
400 case GCL_CBCLSEXTRA: //TODO (doesn't affect allocated classes, so what does it do?)
401 rc = nrExtraClassWords;
402// nrExtraClassWords = lNewVal;
403 break;
404 case GCL_CBWNDEXTRA:
405 rc = nrExtraWindowWords;
406 nrExtraWindowWords = lNewVal;
407 break;
408 case GCL_HBRBACKGROUND:
409 rc = backgroundBrush;
410 backgroundBrush = lNewVal;
411 break;
412 case GCL_HCURSOR:
413 rc = hCursor;
414 hCursor = lNewVal;
415 break;
416 case GCL_HICON:
417 rc = hIcon;
418 hIcon = lNewVal;
419 break;
420 case GCL_HMODULE:
421 rc = hInstance;
422 hInstance = lNewVal;
423 break;
424 case GCL_MENUNAME:
425 rc = 0; //old value is meaningless (according to Wine)
426 setMenuName((LPSTR)lNewVal);
427 break;
428 case GCL_STYLE:
429 rc = windowStyle;
430 windowStyle = lNewVal;
431 break;
432 case GCL_WNDPROC:
433 rc = (LONG)WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A );
434 WINPROC_SetProc((HWINDOWPROC *)&windowProc, (WNDPROC)lNewVal, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS );
435 break;
436 case GCW_ATOM: //TODO: does this really happen in windows?
437 SetLastError(ERROR_INVALID_PARAMETER);
438 return 0;
439 default:
440 if(index > 0 && index < nrExtraClassWords - sizeof(ULONG)) {
441 rc = userClassLong[index];
442 userClassLong[index] = lNewVal;
443 return(rc);
444 }
445 SetLastError(ERROR_INVALID_PARAMETER);
446 return 0;
447 }
448 return(rc);
449}
450//******************************************************************************
451//******************************************************************************
452WORD Win32WndClass::setClassWord(int index, WORD wNewVal)
453{
454 WORD rc;
455
456 switch(index) {
457 case GCW_ATOM:
458 rc = (WORD)classAtom;
459 classAtom = wNewVal;
460 return(rc);
461 default:
462 if(index > 0 && index < nrExtraClassWords - sizeof(WORD)) {
463 rc = ((WORD *)userClassLong)[index];
464 ((WORD *)userClassLong)[index] = wNewVal;
465 return(rc);
466 }
467 SetLastError(ERROR_INVALID_PARAMETER);
468 return 0;
469 }
470}
471//******************************************************************************
472//FIXME: Windows that still exists with this class
473//******************************************************************************
474void Win32WndClass::UnregisterClassA(HINSTANCE hinst, LPSTR id)
475{
476 Win32WndClass *wndclass;
477
478 wndclass = FindClass(hinst, id);
479 if(wndclass) {
480 delete wndclass;
481 return;
482 }
483 dprintf(("::UnregisterClass, couldn't find class %X!!\n", id));
484}
485//******************************************************************************
486//******************************************************************************
487GenericObject *Win32WndClass::wndclasses = NULL;
Note: See TracBrowser for help on using the repository browser.