#include #ifdef WIN32 #include #endif #include #include #include #include #include #define tag L"wa3_resizerclass" extern HINSTANCE hInstance; //---------------------------------------------------------------------- resizeClass::resizeClass(ifc_window *wnd, int minx, int miny, int maxx, int maxy, int sugx, int sugy) { screenWidth = Wasabi::Std::getScreenWidth(); screenHeight = Wasabi::Std::getScreenHeight(); #if defined (_WIN32) || defined(_WIN64) WNDCLASSW wc; if (!GetClassInfoW(hInstance, tag, &wc)) { MEMSET(&wc, 0, sizeof(wc)); wc.lpfnWndProc = resizeWndProc; wc.hInstance = hInstance; // hInstance of DLL wc.lpszClassName = tag; // our window class name wc.style = 0; int _r = RegisterClassW(&wc); ASSERTPR(_r, "cannot create resizer wndclass"); } hWnd = CreateWindowExW(0, tag, L"", 0, 0, 0, 1, 1, NULL, NULL, hInstance, NULL); ASSERT(hWnd); SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)this); if (minx > maxx && maxx != -1) minx = maxx; if (miny > maxy && maxy != -1) miny = maxy; #endif minWinWidth = minx; minWinHeight = miny; maxWinWidth = maxx; maxWinHeight = maxy; sugWinWidth = sugx; sugWinHeight = sugy; if (wnd->getInterface(layoutGuid)) { static_cast(wnd)->getSnapAdjust(&snapAdjust); if (minWinWidth != -1) minWinWidth -= snapAdjust.left + snapAdjust.right; if (minWinHeight != -1) minWinHeight -= snapAdjust.bottom + snapAdjust.top; if (maxWinWidth != -1) maxWinWidth -= snapAdjust.left + snapAdjust.right; if (maxWinHeight != -1) maxWinHeight -= snapAdjust.bottom + snapAdjust.top; if (sugWinWidth != -1) sugWinWidth -= snapAdjust.left + snapAdjust.right; if (sugWinHeight != -1) sugWinHeight -= snapAdjust.bottom + snapAdjust.top; } dc = NULL; #ifdef WIN32 oldB = NULL; brush = NULL; oldP = NULL; pen = NULL; #endif } //---------------------------------------------------------------------- resizeClass::~resizeClass() { #ifdef WIN32 if (dc) { SelectObject(dc, oldB); SelectObject(dc, oldP); SetROP2(dc, mix); DeleteObject(pen); DeleteObject(brush); ReleaseDC(NULL, dc); } if (IsWindow(hWnd)) DestroyWindow(hWnd); //BU win98 sucks UnregisterClass(tag, Main::gethInstance()); #else if (dc) { XFreeGC(Linux::getDisplay(), dc->gc); FREE(dc); } #endif } //---------------------------------------------------------------------- BOOL CALLBACK invalidateChildren(HWND hwnd, LPARAM lParam) { InvalidateRect(hwnd, NULL, FALSE); return TRUE; } //---------------------------------------------------------------------- BOOL CALLBACK invalidateAll(HWND hwnd, LPARAM lParam) { EnumChildWindows(hwnd, invalidateChildren, 0); InvalidateRect(hwnd, NULL, FALSE); return TRUE; } //---------------------------------------------------------------------- int resizeClass::resizeWindow(ifc_window *wnd, int way) { // paintHookStart(); wnd->getWindowRect(&originalRect); snapAdjust.left = 0; snapAdjust.top = 0; snapAdjust.right = 0; snapAdjust.bottom = 0; if (wnd->getInterface(layoutGuid)) { static_cast(wnd)->getSnapAdjust(&snapAdjust); if (wnd->getRenderRatio() != 1.0) { double rr = wnd->getRenderRatio(); snapAdjust.left = (int)((double)(snapAdjust.left) * rr); snapAdjust.top = (int)((double)(snapAdjust.top) * rr); snapAdjust.right = (int)((double)(snapAdjust.right) * rr); snapAdjust.bottom = (int)((double)(snapAdjust.bottom) * rr); } originalRect.left += snapAdjust.left; originalRect.top += snapAdjust.top; originalRect.right -= snapAdjust.right; originalRect.bottom -= snapAdjust.bottom; } curRect = originalRect; resizeWay = way; resizedWindow = wnd->gethWnd(); resizedWindowR = wnd; POINT pt; Wasabi::Std::getMousePos(&pt); cX = pt.x; cY = pt.y; #ifdef WIN32 SetCapture(hWnd); #endif SetTimer(hWnd, 1, 100, NULL); // this timer will make sure that we never get interlock drawFrame(); MSG msg; cancelit = 1; while (GetCapture() == hWnd && GetMessage( &msg, hWnd, 0, 0 )) { TranslateMessage( &msg ); #ifdef LINUX if ( msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE ) wndProc( msg.hwnd, msg.message, msg.wParam, msg.lParam ); else #endif DispatchMessage( &msg ); } drawFrame(); // paintHookStop(); if (GetCapture() == hWnd) ReleaseCapture(); KillTimer(hWnd, 1); if (!cancelit) { curRect.left -= snapAdjust.left; curRect.top -= snapAdjust.top; curRect.right += snapAdjust.right; curRect.bottom += snapAdjust.bottom; } else { curRect = originalRect; // evil, but less evil than InvalidateRect(NULL, NULL, FALSE); EnumWindows(invalidateAll, 0); } return !cancelit; } //---------------------------------------------------------------------- RECT resizeClass::getRect(void) { return curRect; } //#define nifty //---------------------------------------------------------------------- void resizeClass::drawFrame(void) { RECT outRect; #ifdef WIN32 if (!dc) { dc = GetDC(NULL); brush = CreateSolidBrush(0xFFFFFF); pen = CreatePen(PS_SOLID, 0, 0xFFFFFF); oldB = (HBRUSH)SelectObject(dc, brush); oldP = (HPEN)SelectObject(dc, pen); mix = SetROP2(dc, R2_XORPEN); } outRect = curRect; #ifndef nifty DrawFocusRect(dc, &outRect); #else RECT inRect; inRect = outRect; inRect.left += 10; inRect.right -= 10; inRect.top += 24; inRect.bottom -= 10; MoveToEx(dc, inRect.left, inRect.top, NULL); LineTo(dc, inRect.right, inRect.top); LineTo(dc, inRect.right, inRect.bottom); LineTo(dc, inRect.left, inRect.bottom); LineTo(dc, inRect.left, inRect.top); MoveToEx(dc, outRect.left, 0, NULL); LineTo(dc, outRect.left, screenHeight); MoveToEx(dc, outRect.right, 0, NULL); LineTo(dc, outRect.right, screenHeight); MoveToEx(dc, 0, outRect.top, NULL); LineTo(dc, screenWidth, outRect.top); MoveToEx(dc, 0, outRect.bottom, NULL); LineTo(dc, screenWidth, outRect.bottom); #endif #endif//WIN32 #ifdef LINUX outRect = curRect; if ( ! dc ) { dc = (HDC)MALLOC( sizeof( hdc_typ ) ); XGCValues gcv; gcv.function = GXxor; gcv.subwindow_mode = IncludeInferiors; gcv.foreground = 0xffffff; gcv.line_style = LineOnOffDash; gcv.dashes = 1; dc->gc = XCreateGC( Linux::getDisplay(), Linux::RootWin(), GCFunction | GCForeground | GCSubwindowMode, &gcv ); } XDrawRectangle( Linux::getDisplay(), Linux::RootWin(), dc->gc, outRect.left, outRect.top, outRect.right - outRect.left, outRect.bottom - outRect.top ); #endif //PORTME } LRESULT resizeClass::wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_LBUTTONUP: cancelit = 0; ReleaseCapture(); return 0; case WM_MOUSEMOVE: { POINT pt; int iX, iY; Wasabi::Std::getMousePos(&pt); iX = pt.x - cX; iY = pt.y - cY; drawFrame(); if (resizeWay & TOP) curRect.top = originalRect.top + iY; if (resizeWay & BOTTOM) curRect.bottom = originalRect.bottom + iY; if (resizeWay & LEFT) curRect.left = originalRect.left + iX; if (resizeWay & RIGHT) curRect.right = originalRect.right + iX; if (abs((curRect.right - curRect.left) - sugWinWidth) < 10) if (resizeWay & RIGHT) curRect.right = curRect.left + sugWinWidth; else if (resizeWay & LEFT) curRect.left = curRect.right - sugWinWidth; if (abs((curRect.bottom - curRect.top) - sugWinHeight) < 10) if (resizeWay & BOTTOM) curRect.bottom = curRect.top + sugWinHeight; else if (resizeWay & TOP) curRect.top = curRect.bottom - sugWinHeight; curRect.left -= snapAdjust.left; curRect.top -= snapAdjust.top; curRect.right += snapAdjust.right; curRect.bottom += snapAdjust.bottom; windowTracker->autoDock(resizedWindowR, &curRect, resizeWay); curRect.left += snapAdjust.left; curRect.top += snapAdjust.top; curRect.right -= snapAdjust.right; curRect.bottom -= snapAdjust.bottom; if ((curRect.right - curRect.left) < minWinWidth) if (resizeWay & RIGHT) curRect.right = curRect.left + minWinWidth; else if (resizeWay & LEFT) curRect.left = curRect.right - minWinWidth; if ((curRect.bottom - curRect.top) < minWinHeight) if (resizeWay & BOTTOM) curRect.bottom = curRect.top + minWinHeight; else if (resizeWay & TOP) curRect.top = curRect.bottom - minWinHeight; if (maxWinWidth != -1 && (curRect.right - curRect.left) > maxWinWidth) if (resizeWay & RIGHT) curRect.right = curRect.left + maxWinWidth; else if (resizeWay & LEFT) curRect.left = curRect.right - maxWinWidth; if (maxWinHeight != -1 && (curRect.bottom - curRect.top) > maxWinHeight) if (resizeWay & BOTTOM) curRect.bottom = curRect.top + maxWinHeight; else if (resizeWay & TOP) curRect.top = curRect.bottom - maxWinHeight; drawFrame(); } return 0; } #ifdef WIN32 return DefWindowProcW(hwnd, uMsg, wParam, lParam); #else return 0; #endif } // Window Procedure // LRESULT CALLBACK resizeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { #ifdef WIN32 resizeClass *gThis = (resizeClass *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); if (!gThis) return DefWindowProcW(hwnd, uMsg, wParam, lParam); else return gThis->wndProc(hwnd, uMsg, wParam, lParam); #else return 0; #endif } void resizeClass::setResizeCursor(int action) {}