Make controls redraw themselves immediately in certain situations

Michael Kaufmann hallo at michael-kaufmann.ch
Sat Oct 9 17:42:23 CDT 2004


I've sent this patch to wine-devel before, please have a look for 
explanations and a demo program: 
http://www.winehq.org/hypermail/wine-devel/2004/09/0535.html

Changelog:
  - Combobox: Redraw immediately if the current selection is changed
  - Edit control: Redraw immediately if the user types something and 
upon EM_REPLACESEL, EM_SETSEL, WM_CLEAR, WM_PASTE, WM_CUT
  - Listbox: Redraw immediately if the current selection is changed and 
upon LB_SETCURSEL, LB_SETTOPINDEX
  - Static control: Redraw immediately if the text is changed
  - Progress control: Redraw immediately if the "progress value" is changed
  - Statusbar: Redraw immediately if the displayed text is changed
  - Tab control: Redraw immediately if the tab is changed
  - Trackbar: Redraw immediately if the thumb position or the selection 
is changed
  - Treeview: Redraw before sending a notification message if the user 
changes the selection
  - Added new tests

-------------- next part --------------
Index: dlls/comctl32/progress.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/progress.c,v
retrieving revision 1.38
diff -u -r1.38 progress.c
--- dlls/comctl32/progress.c	25 Aug 2004 17:33:01 -0000	1.38
+++ dlls/comctl32/progress.c	9 Oct 2004 21:17:51 -0000
@@ -485,7 +485,7 @@
     infoPtr->MinVal = low;
     infoPtr->MaxVal = high;
     PROGRESS_CoercePos(infoPtr);
-    InvalidateRect(infoPtr->Self, NULL, TRUE);
+    RedrawWindow(infoPtr->Self, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
     return res;
 }
 
@@ -562,6 +562,7 @@
 	    PROGRESS_CoercePos (infoPtr);
 	    TRACE("PBM_DELTAPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
             PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
+	    UpdateWindow(infoPtr->Self);
         }
         return oldVal;
     }
@@ -575,6 +576,7 @@
 	    PROGRESS_CoercePos(infoPtr);
 	    TRACE("PBM_SETPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
             PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
+	    UpdateWindow(infoPtr->Self);
         }
         return oldVal;
     }
@@ -601,6 +603,7 @@
 	{
 	    TRACE("PBM_STEPIT: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal);
             PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal );
+	    UpdateWindow(infoPtr->Self);
 	}
         return oldVal;
     }
Index: dlls/comctl32/status.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/status.c,v
retrieving revision 1.66
diff -u -r1.66 status.c
--- dlls/comctl32/status.c	14 Sep 2004 00:45:26 -0000	1.66
+++ dlls/comctl32/status.c	9 Oct 2004 21:17:52 -0000
@@ -539,14 +539,14 @@
 	    return TRUE;
 	infoPtr->part0.hIcon = hIcon;
 	if (infoPtr->simple)
-            InvalidateRect(infoPtr->Self, &infoPtr->part0.bound, FALSE);
+	    RedrawWindow(infoPtr->Self, &infoPtr->part0.bound, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
     } else {
 	if (infoPtr->parts[nPart].hIcon == hIcon) /* same as - no redraw */
 	    return TRUE;
 
 	infoPtr->parts[nPart].hIcon = hIcon;
 	if (!(infoPtr->simple))
-            InvalidateRect(infoPtr->Self, &infoPtr->parts[nPart].bound, FALSE);
+	    RedrawWindow(infoPtr->Self, &infoPtr->parts[nPart].bound, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
     }
     return TRUE;
 }
@@ -641,7 +641,7 @@
 	}
     }
     STATUSBAR_SetPartBounds (infoPtr);
-    InvalidateRect(infoPtr->Self, NULL, FALSE);
+    RedrawWindow(infoPtr->Self, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
     return TRUE;
 }
 
@@ -708,7 +708,7 @@
 	    Free (part->text);
 	part->text = ntext;
     }
-    InvalidateRect(infoPtr->Self, &part->bound, FALSE);
+    RedrawWindow(infoPtr->Self, &part->bound, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return TRUE;
 }
@@ -780,7 +780,8 @@
     nmhdr.idFrom = GetWindowLongPtrW (infoPtr->Self, GWLP_ID);
     nmhdr.code = SBN_SIMPLEMODECHANGE;
     SendMessageW (infoPtr->Notify, WM_NOTIFY, 0, (LPARAM)&nmhdr);
-    InvalidateRect(infoPtr->Self, NULL, FALSE);
+    RedrawWindow(infoPtr->Self, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+
     return TRUE;
 }
 
@@ -839,9 +840,7 @@
     i = SendMessageW(infoPtr->Notify, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY);
     infoPtr->NtfUnicode = (i == NFR_UNICODE);
 
-    GetClientRect (hwnd, &rect);
-    InvalidateRect (hwnd, &rect, 0);
-    UpdateWindow(hwnd);
+    RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     ZeroMemory (&nclm, sizeof(nclm));
     nclm.cbSize = sizeof(nclm);
@@ -1051,7 +1050,7 @@
 	}
     }
 
-    InvalidateRect(infoPtr->Self, &part->bound, FALSE);
+    RedrawWindow(infoPtr->Self, &part->bound, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return TRUE;
 }
Index: dlls/comctl32/tab.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/tab.c,v
retrieving revision 1.100
diff -u -r1.100 tab.c
--- dlls/comctl32/tab.c	9 Oct 2004 02:27:00 -0000	1.100
+++ dlls/comctl32/tab.c	9 Oct 2004 21:17:54 -0000
@@ -239,6 +239,7 @@
       infoPtr->iSelected=iItem;
       TAB_EnsureSelectionVisible(hwnd, infoPtr);
       TAB_InvalidateTabArea(hwnd, infoPtr);
+      UpdateWindow(hwnd);
   }
   return prevItem;
 }
Index: dlls/comctl32/trackbar.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/trackbar.c,v
retrieving revision 1.62
diff -u -r1.62 trackbar.c
--- dlls/comctl32/trackbar.c	14 Sep 2004 00:45:26 -0000	1.62
+++ dlls/comctl32/trackbar.c	9 Oct 2004 21:17:55 -0000
@@ -375,12 +375,6 @@
     TRACKBAR_CalcThumb(infoPtr, infoPtr->lPos, &infoPtr->rcThumb);
 }
 
-static inline void
-TRACKBAR_InvalidateAll(TRACKBAR_INFO * infoPtr)
-{
-    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
-}
-
 static void
 TRACKBAR_InvalidateThumb (TRACKBAR_INFO *infoPtr, LONG thumbPos)
 {
@@ -951,7 +945,8 @@
     infoPtr->lSelMax = 0;
     infoPtr->flags |= TB_SELECTIONCHANGED;
 
-    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+    if (fRedraw)
+        RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return 0;
 }
@@ -966,7 +961,8 @@
         infoPtr->uNumTics = 0;
     }
 
-    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+    if (fRedraw)
+        RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return 0;
 }
@@ -1096,7 +1092,11 @@
 	infoPtr->lPos = infoPtr->lRangeMax;
     infoPtr->flags |= TB_THUMBPOSCHANGED;
 
-    if (fPosition) TRACKBAR_InvalidateThumbMove(infoPtr, oldPos, lPosition);
+    if (fPosition)
+    {
+    	TRACKBAR_InvalidateThumbMove(infoPtr, oldPos, lPosition);
+	UpdateWindow(infoPtr->hwndSelf);
+    }
 
     return 0;
 }
@@ -1121,7 +1121,8 @@
     infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
     if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
 
-    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+    if (fRedraw)
+        RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return 0;
 }
@@ -1139,7 +1140,8 @@
     infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
     if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
 
-    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+    if (fRedraw)
+    	RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return 0;
 }
@@ -1157,7 +1159,8 @@
     infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
     if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
 
-    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+    if (fRedraw)
+        RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return 0;
 }
@@ -1178,7 +1181,8 @@
     if (infoPtr->lSelMax > infoPtr->lRangeMax)
         infoPtr->lSelMax = infoPtr->lRangeMax;
 
-    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+    if (fRedraw)
+        RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return 0;
 }
@@ -1196,7 +1200,8 @@
     if (infoPtr->lSelMax > infoPtr->lRangeMax)
         infoPtr->lSelMax = infoPtr->lRangeMax;
 
-    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+    if (fRedraw)
+        RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return 0;
 }
@@ -1214,7 +1219,8 @@
     if (infoPtr->lSelMin < infoPtr->lRangeMin)
         infoPtr->lSelMin = infoPtr->lRangeMin;
 
-    if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
+    if (fRedraw)
+        RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
 
     return 0;
 }
@@ -1226,7 +1232,7 @@
     if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_FIXEDLENGTH) {
         infoPtr->uThumbLen = iLength;
 	infoPtr->flags |= TB_THUMBSIZECHANGED;
-	InvalidateRect (infoPtr->hwndSelf, &infoPtr->rcThumb, FALSE);
+	RedrawWindow(infoPtr->hwndSelf, &infoPtr->rcThumb, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
     }
 
     return 0;
@@ -1254,8 +1260,8 @@
     }
     infoPtr->tics[infoPtr->uNumTics-1] = lPos;
 
-    TRACKBAR_InvalidateAll(infoPtr);
-
+    RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+    
     return TRUE;
 }
 
@@ -1266,7 +1272,7 @@
     if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_AUTOTICKS) {
         infoPtr->uTicFreq = wFreq;
 	TRACKBAR_RecalculateTics (infoPtr);
-	TRACKBAR_InvalidateAll(infoPtr);
+	RedrawWindow(infoPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
     }
 
     return 0;
@@ -1412,7 +1418,7 @@
 {
     TRACE("\n");
     infoPtr->bFocussed = FALSE;
-    TRACKBAR_InvalidateAll(infoPtr);
+    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 
     return 0;
 }
@@ -1496,7 +1502,7 @@
 {
     TRACE("\n");
     infoPtr->bFocussed = TRUE;
-    TRACKBAR_InvalidateAll(infoPtr);
+    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 
     return 0;
 }
Index: dlls/comctl32/treeview.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/treeview.c,v
retrieving revision 1.156
diff -u -r1.156 treeview.c
--- dlls/comctl32/treeview.c	7 Oct 2004 17:34:31 -0000	1.156
+++ dlls/comctl32/treeview.c	9 Oct 2004 21:17:58 -0000
@@ -4162,7 +4162,9 @@
 	TREEVIEW_Invalidate(infoPtr, NULL);
 	break;
     }
-
+    
+    UpdateWindow(infoPtr->hwnd);
+    
     TRACE("Leaving state %d\n", newSelect ? newSelect->state : 0);
     return TRUE;
 }
Index: dlls/user/combo.c
===================================================================
RCS file: /home/wine/wine/dlls/user/combo.c,v
retrieving revision 1.3
diff -u -r1.3 combo.c
--- dlls/user/combo.c	6 Oct 2004 00:05:07 -0000	1.3
+++ dlls/user/combo.c	9 Oct 2004 21:18:10 -0000
@@ -1156,9 +1156,9 @@
 		 SWP_NOACTIVATE | SWP_SHOWWINDOW);
 
 
-   if( !(lphc->wState & CBF_NOREDRAW) )
-     RedrawWindow( lphc->self, NULL, 0, RDW_INVALIDATE |
-			   RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN );
+   if( !(lphc->wState & CBF_NOREDRAW) && !IsRectEmpty(&lphc->buttonRect) )
+	RedrawWindow ( lphc->self, &lphc->buttonRect, 0, RDW_INVALIDATE |
+	                     RDW_ERASE | RDW_UPDATENOW);
 
    EnableWindow( lphc->hWndLBox, TRUE );
    if (GetCapture() != lphc->self)
@@ -1397,6 +1397,10 @@
 
 		CB_NOTIFY( lphc, CBN_SELCHANGE );
 
+		/* FIXME: Calling this before CB_NOTIFY looks much nicer,
+		          but Windows does it this way */
+		UpdateWindow(lphc->self);
+	
 		/* fall through */
 
 	   case LBN_SETFOCUS:
Index: dlls/user/edit.c
===================================================================
RCS file: /home/wine/wine/dlls/user/edit.c,v
retrieving revision 1.5
diff -u -r1.5 edit.c
--- dlls/user/edit.c	8 Oct 2004 20:50:52 -0000	1.5
+++ dlls/user/edit.c	9 Oct 2004 21:18:13 -0000
@@ -247,7 +247,7 @@
 static BOOL	EDIT_EM_LineScroll(EDITSTATE *es, INT dx, INT dy);
 static BOOL	EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy);
 static LRESULT	EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap);
-static void	EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update, BOOL honor_limit);
+static void	EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update, BOOL honor_limit, BOOL drawImmediately);
 static LRESULT	EDIT_EM_Scroll(EDITSTATE *es, INT action);
 static void	EDIT_EM_ScrollCaret(EDITSTATE *es);
 static void	EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc);
@@ -255,7 +255,7 @@
 static void	EDIT_EM_SetLimitText(EDITSTATE *es, INT limit);
 static void	EDIT_EM_SetMargins(EDITSTATE *es, INT action, INT left, INT right);
 static void	EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c);
-static void	EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap);
+static void	EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap, BOOL drawImmediately);
 static BOOL	EDIT_EM_SetTabStops(EDITSTATE *es, INT count, LPINT tabs);
 static BOOL	EDIT_EM_SetTabStops16(EDITSTATE *es, INT count, LPINT16 tabs);
 static void	EDIT_EM_SetWordBreakProc(EDITSTATE *es, LPARAM lParam);
@@ -348,7 +348,7 @@
 	if(es->style & ES_READONLY)
 	    return;
 
-	EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE);
+	EDIT_EM_ReplaceSel(es, TRUE, empty_stringW, TRUE, TRUE, TRUE);
 }
 
 
@@ -463,15 +463,15 @@
 
 	case EM_SETSEL16:
 		if ((short)LOWORD(lParam) == -1)
-			EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
+			EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE, TRUE);
 		else
-			EDIT_EM_SetSel(es, LOWORD(lParam), HIWORD(lParam), FALSE);
+			EDIT_EM_SetSel(es, LOWORD(lParam), HIWORD(lParam), FALSE, TRUE);
 		if (!wParam)
 			EDIT_EM_ScrollCaret(es);
 		result = 1;
 		break;
 	case EM_SETSEL:
-		EDIT_EM_SetSel(es, wParam, lParam, FALSE);
+		EDIT_EM_SetSel(es, wParam, lParam, FALSE, TRUE);
 		EDIT_EM_ScrollCaret(es);
 		result = 1;
 		break;
@@ -626,7 +626,7 @@
 			MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
 		}
 
-		EDIT_EM_ReplaceSel(es, (BOOL)wParam, textW, TRUE, TRUE);
+		EDIT_EM_ReplaceSel(es, (BOOL)wParam, textW, TRUE, TRUE, TRUE);
 		result = 1;
 
 		if(!unicode)
@@ -1831,7 +1831,7 @@
 				e--;
 		}
 	}
-	EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
+	EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -1857,7 +1857,7 @@
 	e = EDIT_CharFromPos(es, x, y + es->line_height, &after_wrap);
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(es, s, e, after_wrap);
+	EDIT_EM_SetSel(es, s, e, after_wrap, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -1878,7 +1878,7 @@
 			HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
 	else
 		e = strlenW(es->text);
-	EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, after_wrap);
+	EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, after_wrap, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -1901,7 +1901,7 @@
 				e += 2;
 		}
 	}
-	EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
+	EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -1923,7 +1923,7 @@
 			HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL);
 	else
 		e = 0;
-	EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
+	EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -1951,7 +1951,7 @@
 		&after_wrap);
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(es, s, e, after_wrap);
+	EDIT_EM_SetSel(es, s, e, after_wrap, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -1979,7 +1979,7 @@
 		&after_wrap);
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(es, s, e, after_wrap);
+	EDIT_EM_SetSel(es, s, e, after_wrap, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -2005,7 +2005,7 @@
 	e = EDIT_CharFromPos(es, x, y - es->line_height, &after_wrap);
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(es, s, e, after_wrap);
+	EDIT_EM_SetSel(es, s, e, after_wrap, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -2037,7 +2037,7 @@
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(es, s, e, FALSE);
+	EDIT_EM_SetSel(es, s, e, FALSE, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -2067,7 +2067,7 @@
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(es, s, e, FALSE);
+	EDIT_EM_SetSel(es, s, e, FALSE, TRUE);
 	EDIT_EM_ScrollCaret(es);
 }
 
@@ -2917,7 +2917,7 @@
  *	FIXME: handle ES_NUMBER and ES_OEMCONVERT here
  *
  */
-static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update, BOOL honor_limit)
+static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, LPCWSTR lpsz_replace, BOOL send_update, BOOL honor_limit, BOOL drawImmediately)
 {
 	UINT strl = strlenW(lpsz_replace);
 	UINT tl = strlenW(es->text);
@@ -3029,7 +3029,7 @@
 	else
 	    EDIT_CalcLineWidth_SL(es);
 
-	EDIT_EM_SetSel(es, s, s, FALSE);
+	EDIT_EM_SetSel(es, s, s, FALSE, FALSE);
 	es->flags |= EF_MODIFIED;
 	if (send_update) es->flags |= EF_UPDATE;
 	if (hrgn)
@@ -3045,6 +3045,7 @@
 	/* force scroll info update */
 	EDIT_UpdateScrollInfo(es);
 
+	if (drawImmediately) UpdateWindow(es->hwndSelf);
 
 	if(es->flags & EF_UPDATE)
 	{
@@ -3441,7 +3442,7 @@
  *		In other words: this handler is OK
  *
  */
-static void EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap)
+static void EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap, BOOL drawImmediately)
 {
 	UINT old_start = es->selection_start;
 	UINT old_end = es->selection_end;
@@ -3486,6 +3487,8 @@
             }
 	}
         else EDIT_InvalidateText(es, start, old_end);
+	
+	if (drawImmediately) UpdateWindow(es->hwndSelf);
 }
 
 
@@ -3598,10 +3601,10 @@
 	TRACE("before UNDO:insertion length = %d, deletion buffer = %s\n",
 		     es->undo_insert_count, debugstr_w(utext));
 
-	EDIT_EM_SetSel(es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
+	EDIT_EM_SetSel(es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE, FALSE);
 	EDIT_EM_EmptyUndoBuffer(es);
-	EDIT_EM_ReplaceSel(es, TRUE, utext, TRUE, TRUE);
-	EDIT_EM_SetSel(es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
+	EDIT_EM_ReplaceSel(es, TRUE, utext, TRUE, TRUE, FALSE);
+	EDIT_EM_SetSel(es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE, FALSE);
         /* send the notification after the selection start and end are set */
         EDIT_NOTIFY_PARENT(es, EN_CHANGE, "EN_CHANGE");
 	EDIT_EM_ScrollCaret(es);
@@ -3636,7 +3639,7 @@
 				EDIT_MoveDown_ML(es, FALSE);
 			} else {
 				static const WCHAR cr_lfW[] = {'\r','\n',0};
-				EDIT_EM_ReplaceSel(es, TRUE, cr_lfW, TRUE, TRUE);
+				EDIT_EM_ReplaceSel(es, TRUE, cr_lfW, TRUE, TRUE, TRUE);
 			}
 		}
 		break;
@@ -3644,7 +3647,7 @@
 		if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY))
 		{
 			static const WCHAR tabW[] = {'\t',0};
-			EDIT_EM_ReplaceSel(es, TRUE, tabW, TRUE, TRUE);
+			EDIT_EM_ReplaceSel(es, TRUE, tabW, TRUE, TRUE, TRUE);
 		}
 		break;
 	case VK_BACK:
@@ -3653,7 +3656,7 @@
 				EDIT_WM_Clear(es);
 			else {
 				/* delete character left of caret */
-				EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
+				EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE, TRUE);
 				EDIT_MoveBackward(es, TRUE);
 				EDIT_WM_Clear(es);
 			}
@@ -3680,7 +3683,7 @@
 			WCHAR str[2];
  			str[0] = c;
  			str[1] = '\0';
- 			EDIT_EM_ReplaceSel(es, TRUE, str, TRUE, TRUE);
+ 			EDIT_EM_ReplaceSel(es, TRUE, str, TRUE, TRUE, TRUE);
  		}
 		break;
 	}
@@ -3714,7 +3717,7 @@
 			EDIT_WM_Clear(es);
 			break;
 		case EM_SETSEL:
-			EDIT_EM_SetSel(es, 0, (UINT)-1, FALSE);
+			EDIT_EM_SetSel(es, 0, (UINT)-1, FALSE, TRUE);
 			EDIT_EM_ScrollCaret(es);
 			break;
 		default:
@@ -3812,7 +3815,7 @@
         EDIT_EM_EmptyUndoBuffer(es);
 
        if (name && *name) {
-	   EDIT_EM_ReplaceSel(es, FALSE, name, FALSE, TRUE);
+	   EDIT_EM_ReplaceSel(es, FALSE, name, FALSE, TRUE, FALSE);
 	   /* if we insert text to the editline, the text scrolls out
             * of the window, as the caret is placed after the insert
             * pos normally; thus we reset es->selection... to 0 and
@@ -4178,17 +4181,17 @@
 			} else {
 				if (shift) {
 					/* delete character left of caret */
-					EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
+					EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE, TRUE);
 					EDIT_MoveBackward(es, TRUE);
 					EDIT_WM_Clear(es);
 				} else if (control) {
 					/* delete to end of line */
-					EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
+					EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE, TRUE);
 					EDIT_MoveEnd(es, TRUE);
 					EDIT_WM_Clear(es);
 				} else {
 					/* delete character right of caret */
-					EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
+					EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE, TRUE);
 					EDIT_MoveForward(es, TRUE);
 					EDIT_WM_Clear(es);
 				}
@@ -4260,7 +4263,7 @@
 	ll = EDIT_EM_LineLength(es, e);
 	s = li + EDIT_CallWordBreakProc(es, li, e - li, ll, WB_LEFT);
 	e = li + EDIT_CallWordBreakProc(es, li, e - li, ll, WB_RIGHT);
-	EDIT_EM_SetSel(es, s, e, FALSE);
+	EDIT_EM_SetSel(es, s, e, FALSE, TRUE);
 	EDIT_EM_ScrollCaret(es);
 	return 0;
 }
@@ -4284,7 +4287,7 @@
 	SetCapture(es->hwndSelf);
 	EDIT_ConfinePoint(es, &x, &y);
 	e = EDIT_CharFromPos(es, x, y, &after_wrap);
-	EDIT_EM_SetSel(es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap);
+	EDIT_EM_SetSel(es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap, TRUE);
 	EDIT_EM_ScrollCaret(es);
 	es->region_posx = es->region_posy = 0;
 	SetTimer(es->hwndSelf, 0, 100, NULL);
@@ -4343,7 +4346,7 @@
 	es->region_posx = (prex < x) ? -1 : ((prex > x) ? 1 : 0);
 	es->region_posy = (prey < y) ? -1 : ((prey > y) ? 1 : 0);
 	e = EDIT_CharFromPos(es, x, y, &after_wrap);
-	EDIT_EM_SetSel(es, es->selection_start, e, after_wrap);
+	EDIT_EM_SetSel(es, es->selection_start, e, after_wrap, TRUE);
 	EDIT_SetCaretPos(es,es->selection_end,es->flags & EF_AFTER_WRAP);
 	return 0;
 }
@@ -4553,7 +4556,7 @@
 	OpenClipboard(es->hwndSelf);
 	if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
 		src = (LPWSTR)GlobalLock(hsrc);
-		EDIT_EM_ReplaceSel(es, TRUE, src, TRUE, TRUE);
+		EDIT_EM_ReplaceSel(es, TRUE, src, TRUE, TRUE, TRUE);
 		GlobalUnlock(hsrc);
 	}
 	CloseClipboard();
@@ -4654,20 +4657,20 @@
 	    MultiByteToWideChar(CP_ACP, 0, textA, -1, text, countW);
     }
 
-	EDIT_EM_SetSel(es, 0, (UINT)-1, FALSE);
+	EDIT_EM_SetSel(es, 0, (UINT)-1, FALSE, FALSE);
 	if (text) {
 		TRACE("%s\n", debugstr_w(text));
-		EDIT_EM_ReplaceSel(es, FALSE, text, FALSE, FALSE);
+		EDIT_EM_ReplaceSel(es, FALSE, text, FALSE, FALSE, FALSE);
 		if(!unicode)
 		    HeapFree(GetProcessHeap(), 0, text);
 	} else {
 		static const WCHAR empty_stringW[] = {0};
 		TRACE("<NULL>\n");
-		EDIT_EM_ReplaceSel(es, FALSE, empty_stringW, FALSE, FALSE);
+		EDIT_EM_ReplaceSel(es, FALSE, empty_stringW, FALSE, FALSE, FALSE);
 	}
 	es->x_offset = 0;
 	es->flags &= ~EF_MODIFIED;
-	EDIT_EM_SetSel(es, 0, 0, FALSE);
+	EDIT_EM_SetSel(es, 0, 0, FALSE, FALSE);
         /* Send the notification after the selection start and end have been set
          * edit control doesn't send notification on WM_SETTEXT
          * if it is multiline, or it is part of combobox
@@ -4910,7 +4913,7 @@
 
 /*********************************************************************
  *
- *	EDIT_UpdateText
+ *	EDIT_UpdateTextRegion
  *
  */
 static void EDIT_UpdateTextRegion(EDITSTATE *es, HRGN hrgn, BOOL bErase)
Index: dlls/user/listbox.c
===================================================================
RCS file: /home/wine/wine/dlls/user/listbox.c,v
retrieving revision 1.2
diff -u -r1.2 listbox.c
--- dlls/user/listbox.c	5 Oct 2004 22:31:00 -0000	1.2
+++ dlls/user/listbox.c	9 Oct 2004 21:18:16 -0000
@@ -2383,11 +2383,16 @@
             !IS_MULTISELECT(descr))
             descr->anchor_item = caret;
         LISTBOX_MoveCaret( hwnd, descr, caret, TRUE );
-
         if (descr->style & LBS_MULTIPLESEL)
             descr->selected_item = caret;
         else
             LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
+
+        /* If the content has been scrolled, the new items
+         * need to be drawn immediately (Windows does it this way)
+         */
+        UpdateWindow(hwnd);
+
         if (descr->style & LBS_NOTIFY)
         {
             if( descr->lphc )
@@ -2735,7 +2740,9 @@
 
     case LB_SETTOPINDEX16:
     case LB_SETTOPINDEX:
-        return LISTBOX_SetTopItem( hwnd, descr, wParam, TRUE );
+        ret = LISTBOX_SetTopItem( hwnd, descr, wParam, TRUE );
+        UpdateWindow(hwnd); /* Windows does this too */
+        return ret;
 
     case LB_SETCOLUMNWIDTH16:
     case LB_SETCOLUMNWIDTH:
@@ -2854,7 +2861,9 @@
     case LB_SETCURSEL:
         if (IS_MULTISELECT(descr)) return LB_ERR;
         LISTBOX_SetCaretIndex( hwnd, descr, wParam, TRUE );
-        return LISTBOX_SetSelection( hwnd, descr, wParam, TRUE, FALSE );
+        ret = LISTBOX_SetSelection( hwnd, descr, wParam, TRUE, FALSE );
+        UpdateWindow(hwnd); /* Windows does this too */
+        return ret;
 
     case LB_GETSELCOUNT16:
     case LB_GETSELCOUNT:
Index: dlls/user/static.c
===================================================================
RCS file: /home/wine/wine/dlls/user/static.c,v
retrieving revision 1.2
diff -u -r1.2 static.c
--- dlls/user/static.c	5 Oct 2004 04:11:29 -0000	1.2
+++ dlls/user/static.c	9 Oct 2004 21:18:16 -0000
@@ -348,8 +348,6 @@
 		else
 		    lResult = DefWindowProcA( hwnd, WM_SETTEXT, wParam, lParam );
 	    }
-	    if (uMsg == WM_SETTEXT)
-		STATIC_TryPaintFcn( hwnd, full_style );
 	    break;
 	}
 	default:
@@ -360,9 +358,10 @@
 		else
 		    lResult = DefWindowProcA( hwnd, WM_SETTEXT, wParam, lParam );
 	    }
-	    if(uMsg == WM_SETTEXT)
-		InvalidateRect(hwnd, NULL, TRUE);
 	}
+	
+	STATIC_TryPaintFcn( hwnd, full_style );
+	
         return 1; /* success. FIXME: check text length */
 
     case WM_SETFONT:
Index: dlls/user/tests/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/user/tests/Makefile.in,v
retrieving revision 1.11
diff -u -r1.11 Makefile.in
--- dlls/user/tests/Makefile.in	20 Jul 2004 22:09:14 -0000	1.11
+++ dlls/user/tests/Makefile.in	9 Oct 2004 21:18:16 -0000
@@ -14,6 +14,7 @@
 	input.c \
 	listbox.c \
 	msg.c \
+	redraw.c \
 	resource.c \
 	sysparams.c \
 	text.c \
--- /dev/null	2004-08-22 23:26:44.000000000 +0200
+++ dlls/user/tests/redraw.c	2004-10-09 23:34:18.000000000 +0200
@@ -0,0 +1,183 @@
+/* Unit test suite for redraw behaviour (standard controls)
+ *
+ * Copyright 2004 Michael Kaufmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <assert.h>
+#include <windows.h>
+
+#include "wine/test.h"
+
+static const CHAR parent_class[] = "RedrawWindowClass";
+
+static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+  return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+void do_redraw_test ()
+{
+  int i;
+  HWND parent;
+  HWND handle;
+
+
+  /* Register a class for the parent window */
+
+  WNDCLASSA cls;
+
+  cls.style = CS_HREDRAW | CS_VREDRAW;
+  cls.lpfnWndProc = redraw_window_procA;
+  cls.cbClsExtra = 0;
+  cls.cbWndExtra = 0;
+  cls.hInstance = GetModuleHandleA(0);
+  cls.hIcon = LoadIconA(NULL, IDI_APPLICATION);
+  cls.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
+  cls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
+  cls.lpszMenuName = NULL;
+  cls.lpszClassName = parent_class;
+
+  assert(RegisterClassA(&cls));
+
+
+  /* Create the parent window */
+
+  parent = CreateWindowA (parent_class, "Redraw Test",
+                            WS_OVERLAPPEDWINDOW,
+                            0, 0, 200, 200,
+                            NULL, NULL, NULL, 0);
+  
+
+  /* Static control */
+
+  handle = CreateWindow ("STATIC", "Static Test",
+                            (WS_CHILD | WS_VISIBLE | SS_SIMPLE),
+                            0, 0, 200, 200,
+                            parent, NULL, NULL, 0);
+
+  assert (handle);
+
+  ShowWindow(parent, SW_SHOW);
+  UpdateWindow(parent);
+
+  ok(!GetUpdateRect(handle, NULL, FALSE), "GetUpdateRect should return FALSE after UpdateWindow\n");
+
+  SendMessage(handle, WM_SETTEXT, 0, (LPARAM) (LPCTSTR) "New Text");
+  ok(!GetUpdateRect(handle, NULL, FALSE), "WM_SETTEXT: Static control should redraw itself\n");
+
+  assert(DestroyWindow(handle));
+
+
+
+  /* Listbox */
+
+  handle = CreateWindow ("LISTBOX", "ListboxTest",
+                            (WS_CHILD | WS_VISIBLE | (LBS_STANDARD & ~LBS_SORT) | LBS_MULTIPLESEL),
+                            0, 0, 200, 200,
+                            parent, NULL, NULL, 0);
+
+  assert (handle);
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "First added");
+  ok(GetUpdateRect(handle, NULL, FALSE), "LB_ADDSTRING: Listbox should not redraw itself\n");
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage (handle, LB_SETSEL, TRUE, 0);
+  SendMessage (handle, LB_SETSEL, TRUE, 1);
+  ok(GetUpdateRect(handle, NULL, FALSE), "LB_SETSEL: Listbox should not redraw itself\n");
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage (handle, LB_RESETCONTENT, 0, 0);
+  ok(GetUpdateRect(handle, NULL, FALSE), "LB_RESETCONTENT: Listbox should not redraw itself\n");
+
+  /* Add enough items to make scrolling necessary */
+  for (i=0; i < 100; i++) SendMessage(handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Listbox Item");
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage(handle, LB_SETTOPINDEX, 90, 0);
+  ok(!GetUpdateRect(handle, NULL, FALSE), "LB_SETTOPINDEX: Listbox should redraw itself\n");
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage(handle, LB_SETCURSEL, 5, 0);
+  ok(!GetUpdateRect(handle, NULL, FALSE), "LB_SETCURSEL: Listbox should redraw itself\n");
+
+  assert(DestroyWindow(handle));
+
+
+  /* Edit control */
+
+  handle = CreateWindow ("EDIT", "Edit Test",
+                            (WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_AUTOVSCROLL),
+                            0, 0, 200, 200,
+                            parent, NULL, NULL, 0);
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage(handle, WM_SETTEXT, 0, (LPARAM) (LPCTSTR) "New Edit Text");
+  ok(GetUpdateRect(handle, NULL, FALSE), "WM_SETTEXT: Single-line edit control should not redraw itself\n");
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage(handle, EM_REPLACESEL, TRUE, (LPARAM) (LPCTSTR) "Replacement Text");
+  ok(!GetUpdateRect(handle, NULL, FALSE), "EM_REPLACESEL: Single-line edit control should redraw itself\n");  
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage(handle, EM_SETSEL, 0, 10);
+  ok(!GetUpdateRect(handle, NULL, FALSE), "EM_SETSEL: Single-line edit control should redraw itself\n");  
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage(handle, WM_CUT, 0, 0);
+  ok(!GetUpdateRect(handle, NULL, FALSE), "WM_CUT: Single-line edit control should redraw itself\n");  
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage(handle, WM_PASTE, 0, 0);
+  ok(!GetUpdateRect(handle, NULL, FALSE), "WM_PASTE: Single-line edit control should redraw itself\n");  
+
+  UpdateWindow(handle);
+  assert(!GetUpdateRect(handle, NULL, FALSE));
+
+  SendMessage(handle, WM_CLEAR, 0, 0);
+  ok(!GetUpdateRect(handle, NULL, FALSE), "WM_CLEAR: Single-line edit control should redraw itself\n");  
+  
+  assert(DestroyWindow(handle));
+  assert(DestroyWindow(parent));  
+  assert(UnregisterClassA("RedrawWindowClass", GetModuleHandleA(0))); 
+}
+
+START_TEST(redraw)
+{
+  do_redraw_test();
+}


More information about the wine-patches mailing list