Looking at the painting problems of a popular application under Wine I have found that they come from the use of the CS_OWNDC style in its (custom) editing window. The following description shows what the app is essentially doing. Recreating the problem with a test app is easy. - it has a permanently allocated DC that stays used all the time while the editing is done; in my test I used a simple GetDC(hwnd). - it calls BeginPaint (outside of any WM_PAINT message) - Wine reuses then the same DC and set the visible region to nil because the update region is empty. At this point everything performs similarly to Windows. - when EndPaint is called, Wine releases the DC, and restores the clipping region, but not the visible region. This is what differs from Windows. - after that when the app calls GetClipBox on the DC, under Wine the result is then an empty rectangle, under Windows (NT4 SP6) it's the normal window rectangle. My first try was to add this code in ReleaseDC, but I've failed to reproduce the same behaviour under Windows by calling GetDCEX with the same parameters as Wine in BeginPaint. : in this case the visible region is not restored under Windows - so I think that either something like that is really done in EndPaint, or (more probably) the whole BeginPaint/EndPaint is designed differently. ChangeLog: * dlls/user/painting.c Restore visible region in EndPaint for CS_OWNDC windows
Index: dlls/user/painting.c =================================================================== RCS file: /home/wine/wine/dlls/user/painting.c,v retrieving revision 1.1 diff -u -r1.1 painting.c --- dlls/user/painting.c 2001/12/13 01:03:30 1.1 +++ dlls/user/painting.c 2001/12/19 21:10:56 @@ -12,6 +12,7 @@ #include "wine/server.h" #include "win.h" #include "dce.h" +#include "gdi.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(win); @@ -225,6 +226,19 @@ */ BOOL WINAPI EndPaint( HWND hwnd, const PAINTSTRUCT *lps ) { + WND *wnd; + if (hwnd && (wnd = WIN_FindWndPtr(hwnd))) + { /* FIXME : is this appropriate here !? */ + DWORD clsStyle = wnd->clsStyle; + WIN_ReleaseWndPtr(wnd); + if (clsStyle & CS_OWNDC) /* the dc has been reused */ + { /* restore visible region */ + HRGN hrgn=CreateRectRgn(0,0,0,0); + SetHookFlags16( lps->hdc, DCHF_INVALIDATEVISRGN ); + USER_Driver.pGetDC( hwnd, lps->hdc, hrgn, DCX_EXCLUDERGN ); + DeleteObject(hrgn); + } + } ReleaseDC( hwnd, lps->hdc ); ShowCaret( hwnd ); return TRUE;