Hi,
Summary: SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)NewEditWndProc) in Wine differs from Windows.
Background: when a standard built-in window class (such as Edit for example) is registered initially, the window system register the class with two Procedures (procA and ProcW) and assign a handle as WNDPROC to the class. If a Edit window is created using CreateWindowExA, it will be an Ansi Window. If a Edit window is created using CreateWindowExW, it will be an Unicode Window. This fine in Wine.
Problem: I globally subclass the Edit class using SetClassLongW using following code ------------------------------------------------------------------------------------------------------------ HWND hEdit = CreateWindowExA(0,"Edit", "E1",WS_POPUP,0, 0, 1,1,NULL,NULL,NULL,NULL); OldEditWndProc =(WNDPROC)SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)NewEditWndProc); ------------------------------------------------------------------------------------------------------------ After this subclass, Wine behaves different from Windows
In Windows: a new Edit windows created by CreateWindowsExA((0,"Edit",...) is a Still an Ansi Windows a new Edit windows created by CreateWindowsExW((0,"Edit",...) is a Unicode Windows
But in Wine, new Edit windows created by CreateWindowsExA or CreateWindowsExW are all Unicode Windows. I checked wine 1.1 source code , basically the call to SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)NewEditWndProc) has set the Edit class proc to Unicode Only. So regardless how you create the Edit window, it will be Unicode window.
This is understandable but it's different form windows. causing my application to mis-behave.
More problem, the OldEditWndProc returned above is only the procW of Edit class, if we try to undo the subclass with SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)OldEditWndProc ); the Edit class also lost it's procA.
Discussion: How wine could do the same as windows?
SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)NewEditWndProc) should
1. return the proc handle of the class, instead of procW.
2. set both ProcA and ProcW of Edit class to NewEditWndProc. so NewEditWndProc need to handle both messages from Ansi and Unicode Edit control.
I don't know what is the best way to fix this. Please help.
I have posted a Test application on Bugzilla #14350, please try.
Regards Hongbo
_________________________________________________________________ Are you paid what you're worth? Find out: SEEK Salary Centre http://a.ninemsn.com.au/b.aspx?URL=http%3A%2F%2Fninemsn%2Eseek%2Ecom%2Eau%2F...
Hi,
I have write a patch for the problem, please comment.
=========================================================================== --- wine-1.1.0-orig/dlls/user32/class.c 2008-06-28 00:24:42.000000000 +1000 +++ wine-1.1.0/dlls/user32/class.c 2008-07-10 17:35:11.000000000 +1000 @@ -906,9 +906,18 @@ static ULONG_PTR CLASS_SetClassLong( HWN retval = 0; /* Old value is now meaningless anyway */ break; case GCLP_WNDPROC: - retval = (ULONG_PTR)WINPROC_GetProc( class->winproc, unicode ); - class->winproc = WINPROC_AllocProc( unicode ? NULL : (WNDPROC)newval, - unicode ? (WNDPROC)newval : NULL ); + if( unicode && class->winproc == EDIT_winproc_handle ) + { + retval = class->winproc; + /* if subclassing Edit class, WndProc must handle both Ansi and Unicode Message*/ + class->winproc = WINPROC_AllocProc( (WNDPROC)newval, (WNDPROC)newval ); + } + else + { + retval = (ULONG_PTR)WINPROC_GetProc( class->winproc, unicode ); + class->winproc = WINPROC_AllocProc( unicode ? NULL : (WNDPROC)newval, + unicode ? (WNDPROC)newval : NULL ); + } break; case GCLP_HBRBACKGROUND: retval = (ULONG_PTR)class->hbrBackground;
--- wine-1.1.0-orig/dlls/user32/winproc.c 2008-06-28 00:24:42.000000000 +1000 +++ wine-1.1.0/dlls/user32/winproc.c 2008-07-10 17:35:11.000000000 +1000 @@ -145,7 +145,7 @@ static inline WINDOWPROC *alloc_winproc( /* check if we already have a winproc for that function */ if (!(proc = find_winproc( funcA, funcW ))) { - if (funcA && funcW) + if (funcA && funcW && builtin_used < BUILTIN_WINPROCS ) { assert( builtin_used < BUILTIN_WINPROCS ); proc = &winproc_array[builtin_used++];
===================================================================================== ________________________________
From: hongbo_ni@hotmail.com To: wine-devel@winehq.org Subject: user32: Problem using SetClassLongW to subclass built-in control (Edit) Date: Wed, 9 Jul 2008 22:06:22 +1000
Hi,
Summary: SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)NewEditWndProc) in Wine differs from Windows.
Background: when a standard built-in window class (such as Edit for example) is registered initially, the window system register the class with two Procedures (procA and ProcW) and assign a handle as WNDPROC to the class. If a Edit window is created using CreateWindowExA, it will be an Ansi Window. If a Edit window is created using CreateWindowExW, it will be an Unicode Window. This fine in Wine.
Problem: I globally subclass the Edit class using SetClassLongW using following code
HWND hEdit = CreateWindowExA(0,"Edit", "E1",WS_POPUP,0, 0, 1,1,NULL,NULL,NULL,NULL); OldEditWndProc =(WNDPROC)SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)NewEditWndProc);
After this subclass, Wine behaves different from Windows
In Windows: a new Edit windows created by CreateWindowsExA((0,"Edit",...) is a Still an Ansi Windows a new Edit windows created by CreateWindowsExW((0,"Edit",...) is a Unicode Windows
But in Wine, new Edit windows created by CreateWindowsExA or CreateWindowsExW are all Unicode Windows. I checked wine 1.1 source code , basically the call to SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)NewEditWndProc) has set the Edit class proc to Unicode Only. So regardless how you create the Edit window, it will be Unicode window.
This is understandable but it's different form windows. causing my application to mis-behave.
More problem, the OldEditWndProc returned above is only the procW of Edit class, if we try to undo the subclass with SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)OldEditWndProc ); the Edit class also lost it's procA.
Discussion: How wine could do the same as windows?
SetClassLongW(hEdit, GCL_WNDPROC,(DWORD)NewEditWndProc) should
return the proc handle of the class, instead of procW.
set both ProcA and ProcW of Edit class to NewEditWndProc. so NewEditWndProc need to handle both messages from Ansi and Unicode Edit control.
I don't know what is the best way to fix this. Please help.
I have posted a Test application on Bugzilla #14350, please try.
Regards Hongbo
Find out: SEEK Salary Centre Are you paid what you're worth?
_________________________________________________________________ Are you paid what you're worth? Find out: SEEK Salary Centre http://a.ninemsn.com.au/b.aspx?URL=http%3A%2F%2Fninemsn%2Eseek%2Ecom%2Eau%2F...
2008/7/10 Hongbo Ni hongbo_ni@hotmail.com:
I have write a patch for the problem, please comment.
if( unicode && class->winproc == EDIT_winproc_handle )
Is it just the EDIT window procedure that is affected? I suspect that this will apply to all classes that have A and W variants.
I also suspect that this is wrong. AFAICS, the class name Windows uses is "EDIT", not "EDITA"/"EDITW"; the problem lies in SetWindowProc, so it is likely you need to track both the A and W procs, selecting the appropriate one depending on the variant of SetWindowProc is called. CreateWindow would also need to select the correct one and RegisterWindowClass would need to set the A and W variants initially. However, I am not sure on this, so you need tests.
Also, this patch (when sent to the wine-patches list) will stand a better chance of getting in if there are some tests to verify the behaviour on Windows and deficiency in Wine.
You need to check what procs are returned when. Use your original email as the basis for the test.
Thanks for improving Wine, - Reece
Dear Reece,
Thanks for your comments.
I have write a patch for the problem, please comment.> > + if( unicode && class->winproc == EDIT_winproc_handle )> > Is it just the EDIT window procedure that is affected? I suspect that> this will apply to all classes that have A and W variants.
I encounter this problem with EDIT window. When I look at wine code, i thought the same. But it turn out this is needed only for EDIT, doing the same for other built-in control causing wine to behave different from window. The fact that someone added the var EDIT_winproc_handle is for hacking EDIT class for GetWindowLong. see
---/dlls/user32/win.c line 1911 in WIN_GetWindowLong()---------------------------------- case GWLP_WNDPROC: /* This looks like a hack only for the edit control (see tests). This makes these controls * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests * that the hack is in GetWindowLongPtr[AW], not in winprocs. */ if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE))) retvalue = (ULONG_PTR)wndPtr->winproc; else retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode ); break;--------------------------------------------------------------------------------------------------
I also suspect that this is wrong. AFAICS, the class name Windows uses> is "EDIT", not "EDITA"/"EDITW"; the problem lies in SetWindowProc, so> it is likely you need to track both the A and W procs, selecting the> appropriate one depending on the variant of SetWindowProc is called.> CreateWindow would also need to select the correct one and> RegisterWindowClass would need to set the A and W variants initially.> However, I am not sure on this, so you need tests.
SetWindowProc is for subclass a windows that is already created. It only affects one window. WIN_SetWindowProc will call to WIN_GetWindowLong to return old WndProc. so SetWindowProc will use the same hack for return Edit window WndProc (handle to a struct of ProcA & ProcW). Normally it only return procA or ProcW.
SetClassLongW(hEDIT,GCLP_WNDPROC,proc) for global subclass, and will affect all EDIT windows created after.
for SetClassLong(Ptr), there must be similar hack. That is what I have done, but maybe not totally right.
One thing I am thinking is for Built-in control classes with procA and procW, (Set|Get)ClassLong(hEDIT,GCLP_WNDPROC,proc) should return class->wndproc, so it can be restored later. So similar hack is needed for CLASS_GetClassLong(h,GCLP_WNDPROC..)
But doing this only for EDIT
/* if subclassing Edit class, WndProc must handle both Ansi and Unicode Message*/ class->winproc = WINPROC_AllocProc( (WNDPROC)newval, (WNDPROC)newval );
Also, this patch (when sent to the wine-patches list) will stand a> better chance of getting in if there are some tests to verify the> behaviour on Windows and deficiency in Wine.
I have included a test application with source in bugzilla #14350, the EDIT window on the About dialogbox is non-unicode on Window but Unicode on Wine. My patch fixed that.
You need to check what procs are returned when. Use your original> email as the basis for the test.
(Set|Get)ClassLongW(hEDIT,GCLP_WNDPROC,proc) only retrun procW of the class, so for built-in class with both procA&W, procA is lost in those 2 line of code.
oldProc = SetClassLongW(hEDIT,GCLP_WNDPROC,NewProc); //only return procW. SetClassLong(hEDIT,GCLP_WNDPROC,oldProc); //suppose to restore proc for Edit, but only restored procW, procA lost
because now Edit class only have ProcW, if you call CreateWindowExA('EDIT',..). the created window is Unicode because it will find out it only have procW.
Regards Hongbo
_________________________________________________________________ Are you paid what you're worth? Find out: SEEK Salary Centre http://a.ninemsn.com.au/b.aspx?URL=http%3A%2F%2Fninemsn%2Eseek%2Ecom%2Eau%2F...
Hi Everyone,
It turns out my previous patch was not right to solve the problem.
After writing a win32 application for debuging the impact of SetClassLongW, I found out that something is abnormal in windows.
After a built-in class (which has procA and procW) is subclassed by SetClassLong(Ptr)W(hWnd, GCL_WNDPROC, newProcW);
If you create a window of the same built-in class (such as Edit) using CreateWindow(Ex)A, the created window got it's wnd.procA = class.newProcW. The created window is Ansi.
That is right, the newProcW is going to receive Ansi message - [ABNORMAL]. I have captured the debug screen, here is the screenshot http://www.njstar.com/devimg/SetClassLongW-debug.png
Where in Wine, created window is Unicode, with wnd.procW = class.newProcW. newProcW will only receive Unicode message.
That is the difference between Window and Wine regarding to subclass built-in control. This observation explains exactly what I have seen in my App.
With this knowledge it's now easy to create the patch.
_________________________________________________________________ Windows Live Messenger treats you to 30 free emoticons - Bees, cows, tigers and more! http://livelife.ninemsn.com.au/article.aspx?id=567534
As it was written, you need to write some more tests for such changes. It required a few iterations before we got SetWindowLongPtr(GWLP_WNDPROC, ...) right, so this might be also not easy. The tests for SetWindowLongPtr are in dlls/user32/tests/class.c. Some things I can think of that requires checking:
1. Is the edit class still special after changing the winproc - does the unicodeness of controls created after the SetClassLongPtr call depend on whether CreateWindowA or CreateWindowW was used 2. Does the same winproc really receive both Unicode and ANSI messages. That's the strangest thing in your patch. Does calling SetWindowTextW and SetWindowTextA call the same function, but once with a Unicode string in lparam and the other time with an ANSI string. 3. Does GetClassLongPtr[AW] return an address or a winproc handle (there is a IS_WINPROC_HANDLE macro in dlls/users32/tests/class.c). The same for GetWindowLongPtr[AW]. If point 1 is true then it would be good to check it for controls created with both CreateWindowA and W 4. Does this apply only to the edit class or to all built-in classes. The edit class is special from the point of view of GetWindowLongPtr so it may be also special here.
I think, knowing the answers to these questions would make it easier to create a good patch. This patch seems very strange as it seems unlikely that the same function would be used for both the A and W calls.
Mikołaj
Hello,
Now I have fixed the problem, or corrected to window behaviour. Included is the Patch, Test and Debug (play with windows). Can anyone please test or comment ?
Regards Hongbo Ni
============================================================================== # Patch ============================================================================== --- wine-1.1.1-orig/dlls/user32/win.c 2008-07-12 01:55:55.000000000 +1000 +++ wine-1.1.1/dlls/user32/win.c 2008-07-14 16:49:21.000000000 +1000 @@ -173,6 +173,13 @@ static WND *create_window_handle( HWND p win->owner = full_owner; win->class = class; win->winproc = get_class_winproc( class ); + /* This is a window hack - When builtin Edit class has been subclassed by SetClassLong(Ptr)W */ + /* If creating ansi Edit window & the class does not have a ansi proc, use unicode proc as ansi */ + if(!unicode && !IS_INTRESOURCE(name) && !strcmpiW( name, EDIT_builtin_class.name ) + && WINPROC_IsUnicode( win->winproc, 0 ) && WINPROC_IsUnicode( win->winproc, 1 )) + { + win->winproc = WINPROC_AllocProc((WNDPROC)WINPROC_GetProc( win->winproc, 1 ), NULL); + } win->dwMagic = WND_MAGIC; win->cbWndExtra = extra_bytes; if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
============================================================================== # Debug - following debug shows the window hack # >>show var: is value show by the MSVC debuger ============================================================================== WNDPROC EditWndProcA=NULL, EditClassProcA=NULL; WNDPROC EditWndProcW=NULL, EditClassProcW=NULL; HWND hEditWnd1,hEditWnd2; static const CHAR classNameA[] = "Edit"; static const WCHAR classNameW[] = {'E','d','i','t',0}; int i=0; HWND hEditWnd0 = CreateWindowExA(0,classNameA, NULL,WS_POPUP,0, 0, 1, 1,NULL,NULL,hInst,NULL); EditClassProcA =(WNDPROC)GetClassLongPtrA(hEditWnd0, GCLP_WNDPROC); EditClassProcW =(WNDPROC)GetClassLongPtrW(hEditWnd0, GCLP_WNDPROC); >>show var: EditClassProcA=0x77246feb EditClassProcW=0x7726f52f
EditWndProcA =(WNDPROC)GetWindowLongPtrA(hEditWnd0, GWLP_WNDPROC); EditWndProcW =(WNDPROC)GetWindowLongPtrW(hEditWnd0, GWLP_WNDPROC); >>show var: EditWndProcA =0x77246feb EditWndProcW=0xffff0597(handle)
if(IsWindowUnicode(hEditWnd0)) i++; >>show var: i = 0 -- not a unciode windows
OldEditWndProcW =(WNDPROC)SetClassLongPtrW(hEditWnd0, GCLP_WNDPROC , (DWORD)EditWndProc ); >>show var: OldEditWndProcW=0x7726f52f
EditClassProcA =(WNDPROC)GetClassLongPtrA(hEditWnd1, GCLP_WNDPROC); EditClassProcW =(WNDPROC)GetClassLongPtrW(hEditWnd1, GCLP_WNDPROC); >>show var: EditClassProcA=0xffff05bf EditClassProcW=0x00401014
hEditWnd1 = CreateWindowA(classNameA, NULL,WS_POPUP,0, 16, 100, 16,hWnd,NULL,hInst,NULL); EditWndProcA =(WNDPROC)GetWindowLongPtrA(hEditWnd1, GWLP_WNDPROC); EditWndProcW =(WNDPROC)GetWindowLongPtrW(hEditWnd1, GWLP_WNDPROC); >>show var: EditWndProcA =0x00401014 EditWndProcW=0xffff0637
if(IsWindowUnicode(hEditWnd1)) i++; >>show var: i = 0 -- not a unicode windows
Now you can see EditWndProcA==EditClassProcW and it's not a Unicode Window
I have got a screenshot showing the same debug result on MSVC 6.0 http://www.njstar.com/devimg/SetClassLongW-debug.png
============================================================================== # Test - Following tests are added to dlls/user32/tests/class.c # Latest 4 added tests fails on current wine 1.1.1 ============================================================================== --- wine-1.1.1-orig/dlls/user32/tests/class.c 2008-07-12 01:55:55.000000000 +1000 +++ wine-1.1.1/dlls/user32/tests/class.c 2008-07-14 16:44:34.000000000 +1000 @@ -590,6 +590,7 @@ static void test_builtinproc(void) WCHAR buf[128]; ATOM atom; HWND hwnd; + HWND hwnd2; int i;
pDefWindowProcA = (void *)GetProcAddress(GetModuleHandle("user32.dll"), "DefWindowProcA"); @@ -775,6 +776,72 @@ static void test_builtinproc(void) CallWindowProcA((WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC), hwnd, WM_GETTEXT, 120, (LPARAM)buf); ok(memcmp(buf, classA, sizeof(classA)) == 0, "WM_GETTEXT invalid return\n");
+ /** subclass Edit class using SetClassLongPtrA with ClassTest_WndProc2 **/ + oldproc = (WNDPROC)SetClassLongPtrA( hwnd, GCLP_WNDPROC, (ULONG_PTR)ClassTest_WndProc2); + ok(!IS_WNDPROC_HANDLE(GetClassLongPtrA(hwnd, GCLP_WNDPROC)), + "GetClassLongPtrA expect to return a Ansi wndproc, got %p\n",(void *)GetClassLongPtrA(hwnd, GCLP_WNDPROC)); + ok(IS_WNDPROC_HANDLE(GetClassLongPtrW(hwnd, GCLP_WNDPROC)), + "GetClassLongPtrW expect to return a wndproc handle, got %p\n", (void *)GetClassLongPtrW(hwnd, GCLP_WNDPROC)); + + /* create a unicode edit window */ + hwnd2 = CreateWindowExW(0, WC_EDITW, NULL, WS_POPUP, + 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); + ok(!IsWindowUnicode(hwnd2), "CreateWindowExW should create a Ansi Edit window (subclassed by SetClassLongPtrA)\n"); + ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)), + "GetWindowLongPtrA expect to return a Ansi wndproc, got %p\n",(void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)); + ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)), + "GetWindowLongPtrW expect to return a wndproc handle, got %p\n",(void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)); + DestroyWindow(hwnd2); + + /* create a ansi edit window */ + hwnd2 = CreateWindowExA(0, WC_EDITA, NULL, WS_POPUP, + 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); + ok(!IsWindowUnicode(hwnd2), "CreateWindowExA should create a Ansi Edit window (subclassed by SetClassLongPtrA)\n"); + ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)), + "GetWindowLongPtrA expect to return a Ansi wndproc, got %p\n",(void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)); + ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)), + "GetWindowLongPtrW expect to return a wndproc handle, got %p\n",(void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)); + DestroyWindow(hwnd2); + + SetWindowLongPtrA( hwnd, GCLP_WNDPROC, (ULONG_PTR)oldproc); /* restore procA */ + + /** subclass Edit class using SetClassLongPtrW with ClassTest_WndProc **/ + oldproc = (WNDPROC)SetClassLongPtrW( hwnd, GCLP_WNDPROC, (ULONG_PTR)ClassTest_WndProc); + ok(IS_WNDPROC_HANDLE(GetClassLongPtrA(hwnd, GCLP_WNDPROC)), + "GetClassLongPtrA expect to return a wndproc handle, got %p\n",(void *)GetClassLongPtrA(hwnd, GCLP_WNDPROC)); + ok(!IS_WNDPROC_HANDLE(GetClassLongPtrW(hwnd, GCLP_WNDPROC)), + "GetClassLongPtrW expect to return a Unicode wndproc, got %p\n",(void *)GetClassLongPtrW(hwnd, GCLP_WNDPROC)); + + /* create a unicode edit window */ + hwnd2 = CreateWindowExW(0, WC_EDITW, NULL, WS_POPUP, + 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); + ok(IsWindowUnicode(hwnd2), "CreateWindowExW should create a Unicode Edit window (subclassed by SetClassLongPtrW)\n"); + ok(IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)), + "GetWindowLongPtrA expect to return a wndproc handle, got %p\n",(void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)); + ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)), + "GetWindowLongPtrW expect to return a Unicode wndproc, got %p\n",(void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)); + /* ClassTest_WndProc handles Unciode message - expected */ + ok(((WNDPROC)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)==ClassTest_WndProc), + "GetWindowLongPtrW expect to be ClassTest_WndProc, %p vs %p\n", + (void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC),ClassTest_WndProc); + DestroyWindow(hwnd2); + + /* create a ansi edit window */ + hwnd2 = CreateWindowExA(0, WC_EDITA, NULL, WS_POPUP, + 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); + ok(!IsWindowUnicode(hwnd2), "CreateWindowExA should create a Ansi Edit window (subclassed by SetClassLongPtrW)\n"); + ok(!IS_WNDPROC_HANDLE(GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)), + "GetWindowLongPtrA expect to return a Ansi wndproc, got %p\n",(void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)); + ok(IS_WNDPROC_HANDLE(GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)), + "GetWindowLongPtrW expect to return a wndproc handle, got %p\n",(void *)GetWindowLongPtrW(hwnd2, GWLP_WNDPROC)); + /* ClassTest_WndProc should also handle Ansi message - a window Hack */ + ok(((WNDPROC)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC)==ClassTest_WndProc), + "GetWindowLongPtrA expect to be ClassTest_WndProc, %p vs %p\n", + (void *)GetWindowLongPtrA(hwnd2, GWLP_WNDPROC),ClassTest_WndProc); + DestroyWindow(hwnd2); + + SetWindowLongPtrW( hwnd, GCLP_WNDPROC, (ULONG_PTR)oldproc); /* restore procW */ + DestroyWindow(hwnd); } ==============================================================================
_________________________________________________________________ Meet singles near you. Try ninemsn dating now! http://a.ninemsn.com.au/b.aspx?URL=http%3A%2F%2Fdating%2Eninemsn%2Ecom%2Eau%...
2008/7/14 Hongbo Ni hongbo_ni@hotmail.com:
Now I have fixed the problem, or corrected to window behaviour. Included is the Patch, Test and Debug (play with windows). Can anyone please test or comment ?
Regards Hongbo Ni
==============================================================================
# Patch
--- wine-1.1.1-orig/dlls/user32/win.c 2008-07-12 01:55:55.000000000 +1000 +++ wine-1.1.1/dlls/user32/win.c 2008-07-14 16:49:21.000000000 +1000 @@ -173,6 +173,13 @@ static WND *create_window_handle( HWND p win->owner = full_owner; win->class = class; win->winproc = get_class_winproc( class );
- /* This is a window hack - When builtin Edit class has been subclassed by SetClassLong(Ptr)W */
- /* If creating ansi Edit window & the class does not have a ansi proc, use unicode proc as ansi */
- if(!unicode && !IS_INTRESOURCE(name) && !strcmpiW( name, EDIT_builtin_class.name )
&& WINPROC_IsUnicode( win->winproc, 0 ) && WINPROC_IsUnicode( win->winproc, 1 ))
- {
win->winproc = WINPROC_AllocProc((WNDPROC)WINPROC_GetProc( win->winproc, 1 ), NULL);
- }
It doesn't seem likely that this behaviour just applies to edit controls. More likely, it applies to all builtin classes.
==============================================================================> > # Patch> > ==============================================================================> > --- wine-1.1.1-orig/dlls/user32/win.c 2008-07-12 01:55:55.000000000 +1000> > +++ wine-1.1.1/dlls/user32/win.c 2008-07-14 16:49:21.000000000 +1000> > @@ -173,6 +173,13 @@ static WND *create_window_handle( HWND p> > win->owner = full_owner;> > win->class = class;> > win->winproc = get_class_winproc( class );> > + /* This is a window hack - When builtin Edit class has been subclassed by SetClassLong(Ptr)W */> > + /* If creating ansi Edit window & the class does not have a ansi proc, use unicode proc as ansi */> > + if(!unicode && !IS_INTRESOURCE(name) && !strcmpiW( name, EDIT_builtin_class.name )> > + && WINPROC_IsUnicode( win->winproc, 0 ) && WINPROC_IsUnicode( win->winproc, 1 ))> > + {> > + win->winproc = WINPROC_AllocProc((WNDPROC)WINPROC_GetProc( win->winproc, 1 ), NULL);> > + }> > It doesn't seem likely that this behaviour just applies to edit> controls. More likely, it applies to all builtin classes.> > -- > Rob Shearman
Yes you are right, this behaviour applies to all builtin classes. I can either
1. add more strcmpiW to compare with all the class names,
This can slow down create_window_handle() a little bit.
or 2. prove that there is no need for other builtin classes.
The major difference before Edit and other builtin controls is: the Text in other builtin control does not interact with user, the WM_SETTEXT message do A->W conversion, WM_GETTEXT do a W->A conversion, it can get same string back. so current wine can handle it.
The Edit control interact with user and input system, W->A conversion of SendMessageA(WM_GETTEXT) will not get eact the same string as user entered (eg CJK text). So if we create a Ansi Edit window, we do not want W->A conversion. That is why my patch is needed to make Edit window a Ansi window.
So what do you think we should do?
Regards Hongbo _________________________________________________________________ It's simple! Sell your car for just $40 at CarPoint.com.au http://a.ninemsn.com.au/b.aspx?URL=http%3A%2F%2Fsecure%2Dau%2Eimrworldwide%2...