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

Last change on this file since 5056 was 5056, checked in by sandervl, 25 years ago

class, dialog control size & drawedge fixes

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