void Test_ScrollDC() { HWND hWnd, hWnd2; HDC hDC; HRGN hrgn; RECT rcClip; int iResult; /* Create a window */ hWnd = CreateWindowW(L"BUTTON", L"TestWindow", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 100, 100, NULL, NULL, 0, 0); UpdateWindow(hWnd); hDC = GetDC(hWnd); /* Test that no update region is there */ hrgn = CreateRectRgn(0,0,0,0); iResult = GetUpdateRgn(hWnd, hrgn, FALSE); ok (iResult == NULLREGION, "Expected NULLREGION, got %d\n", iResult); /* Test normal scrolling */ ok(ScrollDC(hDC, 0, 0, NULL, NULL, hrgn, NULL) == TRUE, "ScrollDC failed\n"); /* Scroll with invalid update region */ DeleteObject(hrgn); ok(ScrollDC(hDC, 50, 0, NULL, NULL, (HRGN)0x12345678, NULL) == FALSE, "ScrollDC successed\n"); ok(ScrollDC(hDC, 50, 0, NULL, NULL, hrgn, NULL) == FALSE, "ScrollDC successed\n"); hrgn = CreateRectRgn(0,0,0,0); iResult = GetUpdateRgn(hWnd, hrgn, FALSE); ok(iResult == NULLREGION, "Expected NULLREGION, got %d\n", iResult); /* Scroll with invalid update rect pointer */ ok(ScrollDC(hDC, 50, 0, NULL, NULL, NULL, (PRECT)1) == FALSE, "ScrollDC failed\n"); iResult = GetUpdateRgn(hWnd, hrgn, FALSE); ok(iResult == NULLREGION, "Expected NULLREGION, got %d\n", iResult); /* Scroll with a clip rect */ rcClip.left = 50; rcClip.top = 0; rcClip.right = 100; rcClip.bottom = 100; ok(ScrollDC(hDC, 50, 0, NULL, &rcClip, hrgn, NULL) == TRUE, "ScrollDC failed\n"); iResult = GetUpdateRgn(hWnd, hrgn, FALSE); ok(iResult == NULLREGION, "Expected NULLREGION, got %d\n", iResult); /* Scroll with a clip rect */ rcClip.left = 50; rcClip.top = 0; rcClip.right = 100; rcClip.bottom = 100; ok(ScrollDC(hDC, 50, 50, NULL, &rcClip, hrgn, NULL) == TRUE, "ScrollDC failed\n"); iResult = GetUpdateRgn(hWnd, hrgn, FALSE); ok(iResult == NULLREGION, "Expected NULLREGION, got %d\n", iResult); /* Overlap with another window */ hWnd2 = CreateWindowW(L"BUTTON", L"TestWindow", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 30, 160, 100, 100, NULL, NULL, 0, 0); UpdateWindow(hWnd2); /* Cleanup */ ReleaseDC(hWnd, hDC); DestroyWindow(hWnd); DestroyWindow(hWnd2); }
static void getDirtyRects(HWND window, Vector<CGRect>& outRects) { ASSERT_ARG(outRects, outRects.isEmpty()); RECT clientRect; if (!GetClientRect(window, &clientRect)) return; auto region = adoptGDIObject(::CreateRectRgn(0, 0, 0, 0)); int regionType = GetUpdateRgn(window, region.get(), false); if (regionType != COMPLEXREGION) { RECT dirtyRect; if (GetUpdateRect(window, &dirtyRect, false)) outRects.append(winRectToCGRect(dirtyRect, clientRect)); return; } DWORD dataSize = ::GetRegionData(region.get(), 0, 0); auto regionDataBuffer = std::make_unique<unsigned char[]>(dataSize); RGNDATA* regionData = reinterpret_cast<RGNDATA*>(regionDataBuffer.get()); if (!::GetRegionData(region.get(), dataSize, regionData)) return; outRects.resize(regionData->rdh.nCount); RECT* rect = reinterpret_cast<RECT*>(regionData->Buffer); for (size_t i = 0; i < outRects.size(); ++i, ++rect) outRects[i] = winRectToCGRect(*rect, clientRect); }
void Ctrl::WndUpdate(const Rect& r) { GuiLock __; LLOG("WndUpdate " << UPP::Name(this)); Ctrl *top = GetTopCtrl(); if(top->IsOpen()) { HWND hwnd = top->GetHWND(); HDC hdc = GetDC(hwnd); HRGN hrgn = CreateRectRgn(0, 0, 0, 0); if(GetUpdateRgn(hwnd, hrgn, FALSE) != NULLREGION) { SelectClipRgn(hdc, hrgn); SystemDraw draw(hdc); bool hcr = focusCtrl && focusCtrl->GetTopCtrl() == top && caretRect.Intersects(r + top->GetRect().TopLeft()); if(hcr) ::HideCaret(hwnd); draw.Clip(r); top->UpdateArea(draw, r); ValidateRect(hwnd, r); SelectClipRgn(hdc, NULL); if(hcr) ::ShowCaret(hwnd); } ReleaseDC(hwnd, hdc); DeleteObject(hrgn); } }
static void getDirtyRects(HWND window, Vector<CGRect>& outRects) { ASSERT_ARG(outRects, outRects.isEmpty()); RECT clientRect; if (!GetClientRect(window, &clientRect)) return; HRGN region = CreateRectRgn(0, 0, 0, 0); int regionType = GetUpdateRgn(window, region, false); if (regionType != COMPLEXREGION) { RECT dirtyRect; if (GetUpdateRect(window, &dirtyRect, false)) outRects.append(winRectToCGRect(dirtyRect, clientRect)); return; } DWORD dataSize = GetRegionData(region, 0, 0); OwnArrayPtr<unsigned char> regionDataBuffer(new unsigned char[dataSize]); RGNDATA* regionData = reinterpret_cast<RGNDATA*>(regionDataBuffer.get()); if (!GetRegionData(region, dataSize, regionData)) return; outRects.resize(regionData->rdh.nCount); RECT* rect = reinterpret_cast<RECT*>(regionData->Buffer); for (size_t i = 0; i < outRects.size(); ++i, ++rect) outRects[i] = winRectToCGRect(*rect, clientRect); DeleteObject(region); }
void MCStack::onpaint(void) { HRGN t_update_region; t_update_region = CreateRectRgn(0, 0, 0, 0); GetUpdateRgn((HWND)window -> handle . window, t_update_region, FALSE); PAINTSTRUCT t_paint; BeginPaint((HWND)window -> handle . window, &t_paint); MCGRaster t_mask; MCGRaster *t_mask_ptr; if (MCWin32GetWindowShapeAlphaMask(getwindowshape(), t_mask)) t_mask_ptr = &t_mask; else t_mask_ptr = nil; MCWindowsStackSurface t_surface(t_mask_ptr, t_update_region, t_paint . hdc); if (t_surface.Lock()) { if (s_update_callback == nil) device_redrawwindow(&t_surface, (MCRegionRef)t_update_region); else s_update_callback(&t_surface, (MCRegionRef)t_update_region, s_update_context); t_surface.Unlock(); } EndPaint((HWND)window -> handle . window, &t_paint); DeleteObject(t_update_region); }
void MCStack::onpaint(void) { if (s_update_pixmap == nil) { HRGN t_update_region; t_update_region = CreateRectRgn(0, 0, 0, 0); GetUpdateRgn((HWND)window -> handle . window, t_update_region, FALSE); PAINTSTRUCT t_paint; BeginPaint((HWND)window -> handle . window, &t_paint); MCWindowsStackSurface t_surface(this, t_update_region, t_paint . hdc); redrawwindow(&t_surface, (MCRegionRef)t_update_region); EndPaint((HWND)window -> handle . window, &t_paint); DeleteObject(t_update_region); } else { PAINTSTRUCT t_paint; BeginPaint((HWND)window -> handle . window, &t_paint); HDC t_src_dc = ((MCScreenDC *)MCscreen) -> getsrchdc(); HGDIOBJ t_old_object; t_old_object = SelectObject(t_src_dc, s_update_pixmap -> handle . pixmap); BitBlt(t_paint . hdc, s_update_rect . x, s_update_rect . y, s_update_rect . width, s_update_rect . height, t_src_dc, 0, 0, SRCCOPY); SelectObject(t_src_dc, t_old_object); EndPaint((HWND)window -> handle . window, &t_paint); } }
void Test_ScrollWindowEx() { HWND hWnd; HRGN hrgn; int Result; /* Create a window */ hWnd = CreateWindowW(L"BUTTON", L"TestWindow", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, 0, 0); UpdateWindow(hWnd); /* Assert that no update region is there */ hrgn = CreateRectRgn(0,0,0,0); Result = GetUpdateRgn(hWnd, hrgn, FALSE); ok(Result == NULLREGION, "Result = %d\n", Result); Result = ScrollWindowEx(hWnd, 20, 0, NULL, NULL, NULL, NULL, 0); ok(Result == SIMPLEREGION, "Result = %d\n", Result); Result = GetUpdateRgn(hWnd, hrgn, FALSE); ok(Result == NULLREGION, "Result = %d\n", Result); Result = ScrollWindowEx(hWnd, 20, 0, NULL, NULL, NULL, NULL, SW_INVALIDATE); ok(Result == SIMPLEREGION, "Result = %d\n", Result); Result = GetUpdateRgn(hWnd, hrgn, FALSE); ok(Result == SIMPLEREGION, "Result = %d\n", Result); UpdateWindow(hWnd); // test invalid update region DeleteObject(hrgn); Result = ScrollWindowEx(hWnd, 20, 0, NULL, NULL, hrgn, NULL, SW_INVALIDATE); ok(Result == ERROR, "Result = %d\n", Result); hrgn = CreateRectRgn(0,0,0,0); UpdateWindow(hWnd); // Test invalid updaterect pointer Result = ScrollWindowEx(hWnd, 20, 0, NULL, NULL, NULL, (LPRECT)1, SW_INVALIDATE); ok(Result == ERROR, "Result = %d\n", Result); Result = GetUpdateRgn(hWnd, hrgn, FALSE); ok(Result == SIMPLEREGION, "Result = %d\n", Result); // test for alignment of rects DeleteObject(hrgn); DestroyWindow(hWnd); }
void CChildView::OnPaint() { CPaintDC *dc; CDC *pdc; CRgn ur; ur.CreateRectRgn(0, 0, 0, 0); GetUpdateRgn(&ur); CRect cr; GetClientRect(&cr); if (theApp.m_bStarted && !theApp.m_map.IsEmpty()) { // pdc = &dc; m_MemDC.SelectClipRgn(&ur); pdc = &m_MemDC; theApp.m_map.DrawMap(*pdc, &cr, &ur); CRect r; // r = cr; ur.GetRgnBox(r); // r.InflateRect(1, 1); if (r.left < 0) r.left = 0; if (r.top < 0) r.top = 0; dc = new CPaintDC(this); // device context for painting dc->BitBlt(r.left, r.top, r.Width(), r.Height(), &m_MemDC, r.left, r.top, SRCCOPY); } else { dc = new CPaintDC(this); // device context for painting if (theApp.m_bStarted) { dc->SetTextAlign(TA_CENTER); CPoint cp = cr.CenterPoint(); CString s; s.Format("There are no maps in '%s'", theApp.m_map.m_sMapsPath); dc->ExtTextOut(cp.x, cp.y - dc->GetOutputTextExtent("W").cy/2, ETO_OPAQUE, &cr, s, NULL); } else { dc->FillSolidRect(cr, 0); } } delete dc; }
inline BOOL HookHandle(UINT MessageId, HWND hWnd, WPARAM wParam, LPARAM lParam) { //////////////////////////////////////////////////////////////// // *** HANDLE DEFERRED UPDATES *** // Is this a deferred-update message? if (MessageId == VNC_DEFERRED_UPDATE) { // NOTE : NEVER use the SendDeferred- routines to send updates // from here, or you'll get an infinite loop....! // NB : The format of DEFERRED_UPDATE matches that of UpdateRectMessage, // so just send the exact same message data to WinRFB: PostMessage( hVeneto, UpdateRectMessage, wParam, lParam ); return FALSE; } // *** Could use WM_COPYDATA to send data to WinVNC /* if (GetClassLong(hWnd, GCW_ATOM) == 32768) { _RPT4(_CRT_WARN, "DBG : popup menu message (hwnd=%d, msg=%d, l=%d, w=%d)\n", hWnd, MessageId, lParam, wParam); } */ //////////////////////////////////////////////////////////////// // *** UPDATE-TRIGGERING MESSAGES *** // Do something dependent upon message type switch (MessageId) { //////////////////////////////////////////////////////////////// // Messages indicating only a border repaint. case WM_NCPAINT: case WM_NCACTIVATE: SendDeferredBorderRect(hWnd); break; //////////////////////////////////////////////////////////////// // Messages indicating a client area repaint case WM_CHAR: case WM_KEYUP: // Handle key-presses if (prf_use_KeyPress) SendDeferredWindowRect(hWnd); break; case WM_LBUTTONUP: // Handle LMB clicks if (prf_use_LButtonUp) SendDeferredWindowRect(hWnd); break; case WM_MBUTTONUP: // Handle MMB clicks if (prf_use_MButtonUp) SendDeferredWindowRect(hWnd); break; case WM_RBUTTONUP: // Handle RMB clicks if (prf_use_RButtonUp) SendDeferredWindowRect(hWnd); break; case WM_TIMER: if (prf_use_Timer) SendDeferredWindowRect(hWnd); break; case WM_HSCROLL: case WM_VSCROLL: if (((int) LOWORD(wParam) == SB_THUMBTRACK) || ((int) LOWORD(wParam) == SB_ENDSCROLL)) SendDeferredWindowRect(hWnd); break; case 485: // HACK to handle popup menus { // Get the old popup menu selection value HANDLE prop = GetProp(hWnd, (LPCTSTR) MAKELONG(VNC_POPUPSELN_ATOM, 0)); if (prop != (HANDLE) wParam) { // It did, so update the menu & the selection value SendDeferredWindowRect(hWnd); SetProp(hWnd, (LPCTSTR) MAKELONG(VNC_POPUPSELN_ATOM, 0), (HANDLE) wParam); } } break; //////////////////////////////////////////////////////////////// // Messages indicating a full window update case WM_SYSCOLORCHANGE: case WM_PALETTECHANGED: case WM_SETTEXT: case WM_ENABLE: case BM_SETCHECK: case BM_SETSTATE: case EM_SETSEL: //case WM_MENUSELECT: SendDeferredWindowRect(hWnd); break; //////////////////////////////////////////////////////////////// // Messages indicating that an area of the window needs updating // Uses GetUpdateRect to find out which case WM_PAINT: if (prf_use_GetUpdateRect) { HRGN region; region = CreateRectRgn(0, 0, 0, 0); // Get the affected region if (GetUpdateRgn(hWnd, region, FALSE) != ERROR) { int buffsize; UINT x; RGNDATA *buff; POINT TopLeft; // Get the top-left point of the client area TopLeft.x = 0; TopLeft.y = 0; if (!ClientToScreen(hWnd, &TopLeft)) break; // Get the size of buffer required buffsize = GetRegionData(region, 0, 0); if (buffsize != 0) { buff = (RGNDATA *) new BYTE [buffsize]; if (buff == NULL) break; // Now get the region data if(GetRegionData(region, buffsize, buff)) { for (x=0; x<(buff->rdh.nCount); x++) { // Obtain the rectangles from the list RECT *urect = (RECT *) (((BYTE *) buff) + sizeof(RGNDATAHEADER) + (x * sizeof(RECT))); SendDeferredUpdateRect( hWnd, (SHORT) (TopLeft.x + urect->left), (SHORT) (TopLeft.y + urect->top), (SHORT) (TopLeft.x + urect->right), (SHORT) (TopLeft.y + urect->bottom) ); } } delete [] buff; } } // Now free the region if (region != NULL) DeleteObject(region); } else SendDeferredWindowRect(hWnd); break; //////////////////////////////////////////////////////////////// // Messages indicating full repaint of this and a different window // Send the new position of the window case WM_WINDOWPOSCHANGING: if (IsWindowVisible(hWnd)) SendWindowRect(hWnd); break; case WM_WINDOWPOSCHANGED: if (IsWindowVisible(hWnd)) SendDeferredWindowRect(hWnd); break; //////////////////////////////////////////////////////////////// // WinRFB also wants to know about mouse movement case WM_NCMOUSEMOVE: case WM_MOUSEMOVE: // Inform WinRFB that the mouse has moved and pass it the current cursor handle PostMessage( hVeneto, MouseMoveMessage, (ULONG) GetCursor(), 0 ); break; //////////////////////////////////////////////////////////////// // VNCHOOKS PROPERTIES HANDLING WINDOWS case WM_DESTROY: RemoveProp(hWnd, (LPCTSTR) MAKEWORD(VNC_WINDOWPOS_ATOM, 0)); RemoveProp(hWnd, (LPCTSTR) MAKEWORD(VNC_POPUPSELN_ATOM, 0)); break; } return TRUE; }
static LRESULT CALLBACK window_callback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ALLEGRO_DISPLAY *d = NULL; ALLEGRO_DISPLAY_WIN *win_display = NULL; unsigned int i; ALLEGRO_EVENT_SOURCE *es = NULL; ALLEGRO_SYSTEM *system = al_get_system_driver(); if (message == _al_win_msg_call_proc) { ((void (*)(void*))wParam) ((void*)lParam); return 0; } if (!system) { return DefWindowProc(hWnd,message,wParam,lParam); } if (message == _al_win_msg_suicide && wParam) { win_display = (ALLEGRO_DISPLAY_WIN*)wParam; break_window_message_pump(win_display, hWnd); DestroyWindow(hWnd); return 0; } for (i = 0; i < system->displays._size; i++) { ALLEGRO_DISPLAY **dptr = _al_vector_ref(&system->displays, i); d = *dptr; win_display = (void*)d; if (win_display->window == hWnd) { es = &d->es; break; } } if (i == system->displays._size) return DefWindowProc(hWnd,message,wParam,lParam); if (message == _al_win_msg_suicide) { break_window_message_pump(win_display, hWnd); DestroyWindow(hWnd); return 0; } switch (message) { case WM_INPUT: { /* RAW Input is currently unused. */ UINT dwSize; LPBYTE lpb; RAWINPUT* raw; /* We can't uninstall WM_INPUT mesages. */ if (!al_is_mouse_installed()) break; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); lpb = al_malloc(sizeof(BYTE)*dwSize); if (lpb == NULL) break; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); raw = (RAWINPUT*)lpb; if (raw->header.dwType != RIM_TYPEMOUSE) { al_free(lpb); break; } { RAWMOUSE *rm = &raw->data.mouse; int x = raw->data.mouse.lLastX; int y = raw->data.mouse.lLastY; bool abs = (rm->usFlags & (MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP)) != 0; if (abs || x || y) _al_win_mouse_handle_move(x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) _al_win_mouse_handle_button(1, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_1_UP) _al_win_mouse_handle_button(1, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) _al_win_mouse_handle_button(2, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_2_UP) _al_win_mouse_handle_button(2, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) _al_win_mouse_handle_button(3, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_3_UP) _al_win_mouse_handle_button(3, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) _al_win_mouse_handle_button(4, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_4_UP) _al_win_mouse_handle_button(4, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) _al_win_mouse_handle_button(5, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_5_UP) _al_win_mouse_handle_button(5, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_WHEEL) { SHORT z = (SHORT)rm->usButtonData; _al_win_mouse_handle_wheel(z / WHEEL_DELTA, false, win_display); } } al_free(lpb); break; } case WM_LBUTTONDOWN: case WM_LBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_LBUTTONDOWN); _al_win_mouse_handle_button(1, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_MBUTTONDOWN: case WM_MBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_MBUTTONDOWN); _al_win_mouse_handle_button(3, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_RBUTTONDOWN: case WM_RBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_RBUTTONDOWN); _al_win_mouse_handle_button(2, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_XBUTTONDOWN: case WM_XBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); int button = HIWORD(wParam); bool down = (message == WM_XBUTTONDOWN); if (button == XBUTTON1) _al_win_mouse_handle_button(4, down, mx, my, true, win_display); else if (button == XBUTTON2) _al_win_mouse_handle_button(5, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); return TRUE; } case WM_MOUSEWHEEL: { int d = GET_WHEEL_DELTA_WPARAM(wParam); _al_win_mouse_handle_wheel(d / WHEEL_DELTA, false, win_display); return TRUE; } case WM_MOUSEHWHEEL: { int d = GET_WHEEL_DELTA_WPARAM(wParam); _al_win_mouse_handle_hwheel(d / WHEEL_DELTA, false, win_display); return TRUE; } case WM_MOUSEMOVE: { TRACKMOUSEEVENT tme; int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); if (win_display->mouse_cursor_shown && we_hid_the_mouse) { we_hid_the_mouse = false; win_display->display.vt->hide_mouse_cursor((void*)win_display); } _al_win_mouse_handle_move(mx, my, true, win_display); if (mx >= 0 && my >= 0 && mx < d->w && my < d->h) { tme.cbSize = sizeof(tme); tme.dwFlags = TME_QUERY; if (TrackMouseEvent(&tme) && !tme.hwndTrack) { tme.dwFlags = TME_LEAVE; tme.hwndTrack = hWnd; tme.dwHoverTime = 0; TrackMouseEvent(&tme); _al_win_mouse_handle_enter(win_display); } } /* WM_SETCURSOR messages are not received while the mouse is * captured. We call SetCursor here so that changing the mouse * cursor has an effect while the user is holding down the mouse * button. */ if (GetCapture() == hWnd && win_display->mouse_cursor_shown) { SetCursor(win_display->mouse_selected_hcursor); } break; } case WM_MOUSELEAVE: { _al_win_mouse_handle_leave(win_display); break; } case WM_CAPTURECHANGED: { if (al_is_mouse_installed()) { int i; ALLEGRO_MOUSE_STATE state; if (!lParam || (HWND)lParam == hWnd) break; al_get_mouse_state(&state); for (i = 1; i <= 5; i++) { if (al_mouse_button_down(&state, i)) _al_win_mouse_handle_button(i, 0, 0, 0, true, win_display); } } break; } case WM_NCMOUSEMOVE: { if (!win_display->mouse_cursor_shown) { we_hid_the_mouse = true; win_display->display.vt->show_mouse_cursor((void*)win_display); } break; } case WM_SYSKEYDOWN: { int vcode = wParam; bool extended = (lParam >> 24) & 0x1; bool repeated = (lParam >> 30) & 0x1; _al_win_kbd_handle_key_press(0, vcode, extended, repeated, win_display); break; } case WM_KEYDOWN: { int vcode = wParam; int scode = (lParam >> 16) & 0xff; bool extended = (lParam >> 24) & 0x1; bool repeated = (lParam >> 30) & 0x1; /* We can't use TranslateMessage() because we don't know if it will produce a WM_CHAR or not. */ _al_win_kbd_handle_key_press(scode, vcode, extended, repeated, win_display); break; } case WM_SYSKEYUP: case WM_KEYUP: { int vcode = wParam; int scode = (lParam >> 16) & 0xff; bool extended = (lParam >> 24) & 0x1; _al_win_kbd_handle_key_release(scode, vcode, extended, win_display); break; } case WM_SYSCOMMAND: { if (_al_win_disable_screensaver && ((wParam & 0xfff0) == SC_MONITORPOWER || (wParam & 0xfff0) == SC_SCREENSAVE)) { return 0; } else if ((wParam & 0xfff0) == SC_KEYMENU) { /* Prevent Windows from intercepting the ALT key. (Disables opening menus via the ALT key.) */ return 0; } break; } case WM_PAINT: { if (win_display->display.flags & ALLEGRO_GENERATE_EXPOSE_EVENTS) { RECT r; HRGN hrgn; GetWindowRect(win_display->window, &r); hrgn = CreateRectRgn(r.left, r.top, r.right, r.bottom); if (GetUpdateRgn(win_display->window, hrgn, false) != ERROR) { PAINTSTRUCT ps; DWORD size; LPRGNDATA rgndata; int n; int i; RECT *rects; BeginPaint(win_display->window, &ps); size = GetRegionData(hrgn, 0, NULL); rgndata = al_malloc(size); GetRegionData(hrgn, size, rgndata); n = rgndata->rdh.nCount; rects = (RECT *)rgndata->Buffer; _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_EXPOSE; event.display.timestamp = al_get_time(); for (i = 0; i < n; i++) { event.display.x = rects[i].left; event.display.y = rects[i].top; event.display.width = rects[i].right - rects[i].left; event.display.height = rects[i].bottom - rects[i].top; _al_event_source_emit_event(es, &event); } } _al_event_source_unlock(es); al_free(rgndata); EndPaint(win_display->window, &ps); DeleteObject(hrgn); } return 0; } break; } case WM_SETCURSOR: switch (LOWORD(lParam)) { case HTLEFT: case HTRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZEWE)); break; case HTBOTTOM: case HTTOP: SetCursor(LoadCursor(NULL, IDC_SIZENS)); break; case HTBOTTOMLEFT: case HTTOPRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZENESW)); break; case HTBOTTOMRIGHT: case HTTOPLEFT: SetCursor(LoadCursor(NULL, IDC_SIZENWSE)); break; default: if (win_display->mouse_cursor_shown) { SetCursor(win_display->mouse_selected_hcursor); } else { SetCursor(NULL); } break; } return 1; case WM_ACTIVATE: if (HIWORD(wParam) && LOWORD(wParam) != WA_INACTIVE) break; if (HIWORD(wParam)) d->flags |= ALLEGRO_MINIMIZED; else d->flags &= ~ALLEGRO_MINIMIZED; if (LOWORD(wParam) != WA_INACTIVE) { // Make fullscreen windows TOPMOST again if (d->flags & ALLEGRO_FULLSCREEN_WINDOW) { SetWindowPos(win_display->window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } if (d->vt->switch_in) d->vt->switch_in(d); _al_win_fix_modifiers(); _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; memset(&event, 0, sizeof(event)); event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_IN; event.display.timestamp = al_get_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); _al_win_grab_input(win_display); return 0; } else { // Remove TOPMOST flag from fullscreen windows so we can alt-tab. Also must raise the new activated window if (d->flags & ALLEGRO_FULLSCREEN_WINDOW) { SetWindowPos(win_display->window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); SetWindowPos(GetForegroundWindow(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } // Show the taskbar in case we hid it SetWindowPos(FindWindow("Shell_traywnd", ""), 0, 0, 0, 0, 0, SWP_SHOWWINDOW); if (d->flags & ALLEGRO_FULLSCREEN) { d->vt->switch_out(d); } _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; memset(&event, 0, sizeof(event)); event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_OUT; event.display.timestamp = al_get_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); return 0; } break; case WM_MENUCHAR : return (MNC_CLOSE << 16) | (wParam & 0xffff); case WM_CLOSE: _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; memset(&event, 0, sizeof(event)); event.display.type = ALLEGRO_EVENT_DISPLAY_CLOSE; event.display.timestamp = al_get_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); return 0; case WM_SIZE: if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED) { /* * Delay the resize event so we don't get bogged down with them */ if (!resize_postponed) { resize_postponed = true; _beginthread(postpone_thread_proc, 0, (void *)d); } } return 0; case WM_ENTERSIZEMOVE: /* DefWindowProc for WM_ENTERSIZEMOVE enters a modal loop, which also * ends up blocking the loop in d3d_display_thread_proc (which is * where we are called from, if using D3D). Rather than batching up * intermediate resize events which the user cannot acknowledge in the * meantime anyway, make it so only a single resize event is generated * at WM_EXITSIZEMOVE. */ if (d->flags & ALLEGRO_DIRECT3D) { resize_postponed = true; } break; case WM_EXITSIZEMOVE: if (resize_postponed) { win_generate_resize_event(win_display); win_display->ignore_resize = false; resize_postponed = false; win_display->can_acknowledge = true; } break; } return DefWindowProc(hWnd,message,wParam,lParam); }
static LRESULT CALLBACK window_callback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ALLEGRO_DISPLAY *d = NULL; ALLEGRO_DISPLAY_WIN *win_display = NULL; WINDOWINFO wi; int w; int h; int x; int y; unsigned int i; ALLEGRO_EVENT_SOURCE *es = NULL; ALLEGRO_SYSTEM *system = al_get_system_driver(); wi.cbSize = sizeof(WINDOWINFO); if (message == _al_win_msg_call_proc) { ((void (*)(void*))wParam) ((void*)lParam); return 0; } if (!system) { return DefWindowProc(hWnd,message,wParam,lParam); } if (message == _al_win_msg_suicide && wParam) { win_display = (ALLEGRO_DISPLAY_WIN*)wParam; win_display->end_thread = true; DestroyWindow(hWnd); return 0; } for (i = 0; i < system->displays._size; i++) { ALLEGRO_DISPLAY **dptr = _al_vector_ref(&system->displays, i); d = *dptr; win_display = (void*)d; if (win_display->window == hWnd) { es = &d->es; break; } } if (i == system->displays._size) return DefWindowProc(hWnd,message,wParam,lParam); if (message == _al_win_msg_suicide) { win_display->end_thread = true; DestroyWindow(hWnd); return 0; } switch (message) { case WM_INPUT: { UINT dwSize; LPBYTE lpb; RAWINPUT* raw; /* We can't uninstall WM_INPUT mesages. */ if (!al_is_mouse_installed()) break; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); lpb = malloc(sizeof(BYTE)*dwSize); if (lpb == NULL) break; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); raw = (RAWINPUT*)lpb; if (raw->header.dwType != RIM_TYPEMOUSE) { free(lpb); break; } { RAWMOUSE *rm = &raw->data.mouse; int x = raw->data.mouse.lLastX; int y = raw->data.mouse.lLastY; bool abs = rm->usFlags & (MOUSE_MOVE_ABSOLUTE || MOUSE_VIRTUAL_DESKTOP); if (abs || x || y) _al_win_mouse_handle_move(x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) _al_win_mouse_handle_button(1, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_1_UP) _al_win_mouse_handle_button(1, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) _al_win_mouse_handle_button(2, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_2_UP) _al_win_mouse_handle_button(2, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) _al_win_mouse_handle_button(3, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_3_UP) _al_win_mouse_handle_button(3, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) _al_win_mouse_handle_button(4, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_4_UP) _al_win_mouse_handle_button(4, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) _al_win_mouse_handle_button(5, true, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_BUTTON_5_UP) _al_win_mouse_handle_button(5, false, x, y, abs, win_display); if (rm->usButtonFlags & RI_MOUSE_WHEEL) { SHORT z = (SHORT)rm->usButtonData; _al_win_mouse_handle_wheel(z / WHEEL_DELTA, false, win_display); } } free(lpb); break; } case WM_LBUTTONDOWN: case WM_LBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_LBUTTONDOWN); _al_win_mouse_handle_button(1, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_MBUTTONDOWN: case WM_MBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_MBUTTONDOWN); _al_win_mouse_handle_button(3, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_RBUTTONDOWN: case WM_RBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); bool down = (message == WM_RBUTTONDOWN); _al_win_mouse_handle_button(2, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); break; } case WM_XBUTTONDOWN: case WM_XBUTTONUP: { int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); int button = HIWORD(wParam); bool down = (message == WM_XBUTTONDOWN); if (button == XBUTTON1) _al_win_mouse_handle_button(4, down, mx, my, true, win_display); else if (button == XBUTTON2) _al_win_mouse_handle_button(5, down, mx, my, true, win_display); handle_mouse_capture(down, hWnd); return TRUE; } case WM_MOUSEWHEEL: { int d = GET_WHEEL_DELTA_WPARAM(wParam); _al_win_mouse_handle_wheel(d / WHEEL_DELTA, false, win_display); return TRUE; } case WM_MOUSEMOVE: { TRACKMOUSEEVENT tme; int mx = GET_X_LPARAM(lParam); int my = GET_Y_LPARAM(lParam); if (win_display->mouse_cursor_shown && we_hid_the_mouse) { we_hid_the_mouse = false; win_display->display.vt->hide_mouse_cursor((void*)win_display); } _al_win_mouse_handle_move(mx, my, true, win_display); if (mx >= 0 && my >= 0 && mx < d->w && my < d->h) { tme.cbSize = sizeof(tme); tme.dwFlags = TME_QUERY; if (TrackMouseEvent(&tme) && !tme.hwndTrack) { tme.dwFlags = TME_LEAVE; tme.hwndTrack = hWnd; tme.dwHoverTime = 0; TrackMouseEvent(&tme); _al_win_mouse_handle_enter(win_display); } } break; } case WM_MOUSELEAVE: { _al_win_mouse_handle_leave(win_display); break; } case WM_CAPTURECHANGED: if (al_is_mouse_installed()) { int i; ALLEGRO_MOUSE_STATE state; if (!lParam || (HWND)lParam == hWnd) break; al_get_mouse_state(&state); for (i = 1; i <= 5; i++) { if (al_mouse_button_down(&state, i)) _al_win_mouse_handle_button(i, 0, 0, 0, true, win_display); } break; } case WM_NCMOUSEMOVE: { if (!win_display->mouse_cursor_shown) { we_hid_the_mouse = true; win_display->display.vt->show_mouse_cursor((void*)win_display); } break; } case WM_SYSKEYDOWN: { int vcode = wParam; bool repeated = (lParam >> 30) & 0x1; _al_win_kbd_handle_key_press(0, vcode, repeated, win_display); break; } case WM_KEYDOWN: { int vcode = wParam; int scode = (lParam >> 16) & 0xff; bool repeated = (lParam >> 30) & 0x1; /* We can't use TranslateMessage() because we don't know if it will produce a WM_CHAR or not. */ _al_win_kbd_handle_key_press(scode, vcode, repeated, win_display); break; } case WM_SYSKEYUP: case WM_KEYUP: { int vcode = wParam; _al_win_kbd_handle_key_release(vcode, win_display); break; } case WM_SYSCOMMAND: { if (_al_win_disable_screensaver && ((wParam & 0xfff0) == SC_MONITORPOWER || (wParam & 0xfff0) == SC_SCREENSAVE)) { return 0; } else if ((wParam & 0xfff0) == SC_KEYMENU) { /* Prevent Windows from intercepting the ALT key. (Disables opening menus via the ALT key.) */ return 0; } break; } case WM_PAINT: { if ((win_display->display.flags & ALLEGRO_GENERATE_EXPOSE_EVENTS) && _al_event_source_needs_to_generate_event(es)) { RECT r; HRGN hrgn; GetWindowRect(win_display->window, &r); hrgn = CreateRectRgn(r.left, r.top, r.right, r.bottom); if (GetUpdateRgn(win_display->window, hrgn, false) != ERROR) { PAINTSTRUCT ps; DWORD size; LPRGNDATA rgndata; int n; int i; RECT *rects; BeginPaint(win_display->window, &ps); size = GetRegionData(hrgn, 0, NULL); rgndata = _AL_MALLOC(size); GetRegionData(hrgn, size, rgndata); n = rgndata->rdh.nCount; rects = (RECT *)rgndata->Buffer; //GetWindowInfo(win_display->window, &wi); _al_event_source_lock(es); for (i = 0; i < n; i++) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_EXPOSE; event.display.timestamp = al_current_time(); event.display.x = rects[i].left; event.display.y = rects[i].top; event.display.width = rects[i].right - rects[i].left; event.display.height = rects[i].bottom - rects[i].top; _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); _AL_FREE(rgndata); EndPaint(win_display->window, &ps); DeleteObject(hrgn); } return 0; } break; } case WM_SETCURSOR: switch (LOWORD(lParam)) { case HTLEFT: case HTRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZEWE)); break; case HTBOTTOM: case HTTOP: SetCursor(LoadCursor(NULL, IDC_SIZENS)); break; case HTBOTTOMLEFT: case HTTOPRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZENESW)); break; case HTBOTTOMRIGHT: case HTTOPLEFT: SetCursor(LoadCursor(NULL, IDC_SIZENWSE)); break; default: if (win_display->mouse_cursor_shown) { SetCursor(win_display->mouse_selected_hcursor); } else { SetCursor(NULL); } break; } return 1; case WM_ACTIVATE: if (LOWORD(wParam) != WA_INACTIVE) { /* This SetWindowPos is for faux-fullscreen windows that lost focus * so they can get placed back on top */ // FIXME: this doesn't seem to work //SetWindowPos(win_display->window, HWND_TOP, 0, 0, 0, 0, // SWP_NOMOVE | SWP_NOSIZE); if (d->vt->switch_in) d->vt->switch_in(d); _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_IN; event.display.timestamp = al_current_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); _al_win_grab_input(win_display); return 0; } else { if (d->flags & ALLEGRO_FULLSCREEN) { d->vt->switch_out(d); } _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_SWITCH_OUT; event.display.timestamp = al_current_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); return 0; } break; case WM_MENUCHAR : return (MNC_CLOSE << 16) | (wParam & 0xffff); case WM_CLOSE: _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_CLOSE; event.display.timestamp = al_current_time(); _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); return 0; case WM_SIZE: if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED) { /* * Delay the resize event so we don't get bogged down with them */ if (!resize_postponed) { resize_postponed = true; postpone_resize(win_display->window); } } return 0; case WM_USER+0: /* Generate a resize event if the size has changed. We cannot asynchronously * change the display size here yet, since the user will only know about a * changed size after receiving the resize event. Here we merely add the * event to the queue. */ GetWindowInfo(win_display->window, &wi); x = wi.rcClient.left; y = wi.rcClient.top; w = wi.rcClient.right - wi.rcClient.left; h = wi.rcClient.bottom - wi.rcClient.top; if (d->w != w || d->h != h) { _al_event_source_lock(es); if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_RESIZE; event.display.timestamp = al_current_time(); event.display.x = x; event.display.y = y; event.display.width = w; event.display.height = h; _al_event_source_emit_event(es, &event); } /* Generate an expose event. */ if (_al_event_source_needs_to_generate_event(es)) { ALLEGRO_EVENT event; event.display.type = ALLEGRO_EVENT_DISPLAY_EXPOSE; event.display.timestamp = al_current_time(); event.display.x = x; event.display.y = y; event.display.width = w; event.display.height = h; _al_event_source_emit_event(es, &event); } _al_event_source_unlock(es); } resize_postponed = false; win_display->can_acknowledge = true; return 0; } return DefWindowProc(hWnd,message,wParam,lParam); }
int CALLBACK ButtonX::windowProc(HWND hwnd , int message , WPARAM wParam, LPARAM lParam) { switch(message) { case WM_SETTEXT: ButtonX::fromHWND(hwnd)->_text = (char*) lParam; //break; return 0; case WM_GETTEXT: if (ButtonX::fromHWND(hwnd)->_duringPaint) { ((char*)lParam)[0] = 0; return 0; } //break; // strncpy((char*) lParam,ButtonX::fromHWND(hwnd)->_text , wParam); strncpy((char*) lParam,ButtonX::fromHWND(hwnd)->_text , wParam); return min(ButtonX::fromHWND(hwnd)->_text.length(), wParam-1); case WM_GETTEXTLENGTH: if (ButtonX::fromHWND(hwnd)->_duringPaint) return 0; //break; return ButtonX::fromHWND(hwnd)->_text.length(); case WM_PAINT: { ButtonX * bt = ButtonX::fromHWND(hwnd); //if (!bt->_icon) break; // standardowa obs³uga... //int r = 1; HRGN hrgn=CreateRectRgn(0, 0, 0, 0); bt->_duringPaint=true; GetUpdateRgn(hwnd, hrgn, false); int r = 1; if (!bt->isFlat()) { r = CallWindowProc(ButtonX::buttonClassProc, hwnd, message, wParam, lParam); } InvalidateRgn(hwnd, hrgn, false); PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hwnd, &ps); if (bt->isFlat()) { FillRgn(hdc, hrgn, GetSysColorBrush(COLOR_BTNFACE)); } RECT rc = {0,0,0,0}; bt->drawCaption(hdc, rc); EndPaint(hwnd, &ps); bt->_duringPaint=false; DeleteObject(hrgn); return r;} case WM_ENABLE: case WM_UPDATEUISTATE: { int r = CallWindowProc(ButtonX::buttonClassProc, hwnd, message, wParam, lParam); repaintWindow(hwnd); return r;} case WM_ERASEBKGND: return 0; case WM_SETFOCUS: //case BM_SETSTYLE: case BM_SETSTATE: // specjalnie dla W98 repaintWindow(hwnd); break; case WM_SETCURSOR: if (fromHWND(hwnd)->isFlat()) { SetCursor( LoadCursor(0, IDC_HAND) ); return true; } break; #ifndef STAMINA_KISS case WM_LBUTTONDOWN: { ButtonX* b = fromHWND(hwnd); S_ASSERT(b); b->_pressed = true; b->evtMouseDown(b, wParam); break;} case WM_LBUTTONUP: { ButtonX* b = fromHWND(hwnd); S_ASSERT(b); if (b->_pressed) { b->evtMouseUp(b, wParam); if (getClientRect(hwnd).contains(Point::fromLParam(lParam))) { b->evtClick(b); } } b->_pressed = false; break;} case WM_LBUTTONDBLCLK: { //SendMessage(hwnd, BM_CLICK, 0, 0); ButtonX* b = fromHWND(hwnd); S_ASSERT(b); b->evtMouseDown(b, wParam); b->evtMouseUp(b, wParam); b->evtClick(b); break;} case WM_MOUSELEAVE: //fromHWND(hwnd)->_pressed = false; break; case WM_MOUSEMOVE: _tipTarget->attachButton(fromHWND(hwnd)); ToolTipX::mouseMovement(GetParent(hwnd)); //if (wParam == MK_LBUTTON) { // fromHWND(hwnd)->_pressed = true; //} break; #endif case WM_DESTROY: delete ButtonX::fromHWND(hwnd); break; }; return CallWindowProc(ButtonX::buttonClassProc, hwnd, message, wParam, lParam); }
//----------------------------------------------------------------------------- void Win32Frame::paint (HWND hwnd) { HRGN rgn = CreateRectRgn (0, 0, 0, 0); if (GetUpdateRgn (hwnd, rgn, false) == NULLREGION) { DeleteObject (rgn); return; } inPaint = true; PAINTSTRUCT ps; HDC hdc = BeginPaint (hwnd, &ps); if (hdc) { CRect updateRect ((CCoord)ps.rcPaint.left, (CCoord)ps.rcPaint.top, (CCoord)ps.rcPaint.right, (CCoord)ps.rcPaint.bottom); CRect frameSize; getSize (frameSize); frameSize.offset (-frameSize.left, -frameSize.top); if (deviceContext == 0) deviceContext = createDrawContext (hwnd, hdc, frameSize); if (deviceContext) { deviceContext->setClipRect (updateRect); CDrawContext* drawContext = backBuffer ? backBuffer : deviceContext; drawContext->beginDraw (); DWORD len = GetRegionData (rgn, 0, NULL); if (len) { if (len > updateRegionListSize) { if (updateRegionList) free (updateRegionList); updateRegionListSize = len; updateRegionList = (RGNDATA*) malloc (updateRegionListSize); } GetRegionData (rgn, len, updateRegionList); if (updateRegionList->rdh.nCount > 0) { RECT* rp = (RECT*)updateRegionList->Buffer; for (uint32_t i = 0; i < updateRegionList->rdh.nCount; i++) { CRect ur (rp->left, rp->top, rp->right, rp->bottom); paintRect = ur; drawContext->clearRect (ur); getFrame ()->platformDrawRect (drawContext, ur); rp++; } } else { getFrame ()->platformDrawRect (drawContext, updateRect); } } drawContext->endDraw (); if (backBuffer) { deviceContext->beginDraw (); deviceContext->clearRect (updateRect); backBuffer->copyFrom (deviceContext, updateRect, CPoint (updateRect.left, updateRect.top)); deviceContext->endDraw (); } } } EndPaint (hwnd, &ps); DeleteObject (rgn); inPaint = false; }