Live window resizing on Windows

Custom implementation for resizing (GHOST_SizerWin32)

Some things still don't work:
* esc cancel
* max windows size
* aero (sizing) snap on win7

hbrBackground = 0 to disable clear screen.

Thanks to dfelinto for help in finding of root cause.
This commit is contained in:
Alexander Kuznetsov
2013-04-09 17:21:05 +00:00
parent 13780935dc
commit f652b11ed1
6 changed files with 298 additions and 5 deletions

View File

@@ -296,6 +296,7 @@ elseif(WIN32)
intern/GHOST_SystemPathsWin32.cpp
intern/GHOST_WindowWin32.cpp
intern/GHOST_DropTargetWin32.cpp
intern/GHOST_SizerWin32.cpp
intern/GHOST_DisplayManagerWin32.h
intern/GHOST_DropTargetWin32.h
@@ -303,6 +304,7 @@ elseif(WIN32)
intern/GHOST_SystemPathsWin32.h
intern/GHOST_WindowWin32.h
intern/GHOST_TaskbarWin32.h
intern/GHOST_SizerWin32.h
)
if(WITH_INPUT_NDOF)

View File

@@ -0,0 +1,202 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2013 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Alexandr Kuznetsov
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file ghost/intern/GHOST_SizerWin32.cpp
* \ingroup GHOST
*/
#ifndef __GHOST_SIZERWIN32_CPP__
#define __GHOST_SIZERWIN32_CPP__
#include "GHOST_SizerWin32.h"
#include <Windowsx.h>
#define T_NONE (0)
#define T_SIZE (1)
#define T_MOVE (2)
#define T_MOVESIZE (3)
static void RectCopyH(RECT * t, RECT * f)
{
t->left = f->left;
t->right = f->right;
}
static void RectCopyV(RECT * t, RECT * f)
{
t->top = f->top;
t->bottom = f->bottom;
}
static void RectCopy(RECT * t, RECT * f)
{
RectCopyH(t,f);
RectCopyV(t,f);
}
GHOST_SizerWin32::GHOST_SizerWin32(void)
{
hortransf = vertransf = 0;
minsize[0] = minsize[1] = 0;
hwnd = 0;
}
GHOST_SizerWin32::~GHOST_SizerWin32(void)
{
if(isWinChanges())
cancel();
}
void GHOST_SizerWin32::setMinSize(int minx, int miny)
{
minsize[0] = minx;
minsize[1] = miny;
}
bool GHOST_SizerWin32::isWinChanges(void)
{
return hortransf||vertransf;
}
void GHOST_SizerWin32::startSizing(unsigned short type)
{
//SetCapture(hwnd);
POINT coord;
switch(type & 0xf)
{
case WMSZ_LEFT: hortransf = T_MOVESIZE;
vertransf = T_NONE; break;
case WMSZ_RIGHT: hortransf = T_SIZE;
vertransf = T_NONE; break;
case WMSZ_TOP: hortransf = T_NONE;
vertransf = T_MOVESIZE; break;
case WMSZ_TOPLEFT: hortransf = T_MOVESIZE;
vertransf = T_MOVESIZE; break;
case WMSZ_TOPRIGHT: hortransf = T_SIZE;
vertransf = T_MOVESIZE; break;
case WMSZ_BOTTOM: hortransf = T_NONE;
vertransf = T_SIZE; break;
case WMSZ_BOTTOMLEFT: hortransf = T_MOVESIZE;
vertransf = T_SIZE; break;
case WMSZ_BOTTOMRIGHT: hortransf = T_SIZE;
vertransf = T_SIZE; break;
}
POINT mp;
GetCursorPos(&mp);
startpos[0]=mp.x;
startpos[1]=mp.y;
GetWindowRect(hwnd, &initrect);
initrect.bottom-=initrect.top;
initrect.right-=initrect.left;
RectCopy(&goodrect,&initrect);
}
void GHOST_SizerWin32::setHWND(HWND hWnd)
{
this->hwnd = hWnd;
}
void GHOST_SizerWin32::updateWindowSize(void)
{
if(!isWinChanges())
return;
if(hortransf||vertransf){
POINT mp;
GetCursorPos(&mp);
int hordelta = mp.x-startpos[0];
int verdelta = mp.y-startpos[1];
RECT newrect;
RectCopy(&newrect, &initrect);
switch(hortransf)
{
case T_SIZE:
newrect.right+=hordelta;
break;
case T_MOVESIZE:
newrect.right-=hordelta;
case T_MOVE:
newrect.left+=hordelta;
break;
}
switch(vertransf)
{
case T_SIZE:
newrect.bottom+=verdelta;
break;
case T_MOVESIZE:
newrect.bottom-=verdelta;
case T_MOVE:
newrect.top+=verdelta;
break;
}
if(newrect.right<minsize[0])
RectCopyH(&newrect,&goodrect);
if(newrect.bottom<minsize[1])
RectCopyV(&newrect,&goodrect);
SetWindowPos(hwnd,0,newrect.left, newrect.top,
newrect.right, newrect.bottom,
0);
RectCopy(&goodrect, &newrect);
}
}
void GHOST_SizerWin32::cancel(void)
{
accept();
SetWindowPos(hwnd,0,initrect.left, initrect.top,
initrect.right, initrect.bottom, 0);
}
void GHOST_SizerWin32::accept(void)
{
hortransf=vertransf=0;
}
#endif /* __GHOST_SIZERWIN32_CPP__*/

View File

@@ -0,0 +1,61 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2013 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Alexandr Kuznetsov
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file ghost/intern/GHOST_SizerWin32.h
* \ingroup GHOST
*/
#ifndef __GHOST_SIZERWIN32_H__
#define __GHOST_SIZERWIN32_H__
#include <windows.h>
class GHOST_SizerWin32
{
private:
HWND hwnd;
int startpos[2];
int minsize[2];
RECT initrect;
RECT goodrect;
unsigned char hortransf, vertransf;
public:
GHOST_SizerWin32(void);
~GHOST_SizerWin32(void);
bool isWinChanges(void);
void startSizing(unsigned short type);
void updateWindowSize(void);
void setHWND(HWND hWnd);
void setMinSize(int minx, int miny);
void cancel(void);
void accept(void);
};
#endif /*#ifndef __GHOST_SIZERWIN32_H__*/

View File

@@ -400,7 +400,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
}
if (success) {
WNDCLASSW wc;
WNDCLASSW wc = {0};
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = s_wndProc;
wc.cbClsExtra = 0;
@@ -412,7 +412,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
::LoadIcon(NULL, IDI_APPLICATION);
}
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH) ::GetStockObject(BLACK_BRUSH);
wc.hbrBackground = 0;
wc.lpszMenuName = 0;
wc.lpszClassName = L"GHOST_WindowClass";
@@ -979,7 +979,16 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* maximize, minimize or close the window are triggered. Also it is sent when ALT
* button is press for menu. To prevent this we must return preventing DefWindowProc.
*/
if (wParam == SC_KEYMENU) return 0;
if (wParam == SC_KEYMENU)
{
eventHandled = true;
} else
if((wParam&0xfff0)==SC_SIZE)
{
window->registerMouseClickEvent(0);
window->m_wsh.startSizing(wParam);
eventHandled = true;
}
break;
////////////////////////////////////////////////////////////////////////
// Tablet events, processed
@@ -1017,6 +1026,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
break;
case WM_LBUTTONUP:
window->registerMouseClickEvent(1);
if(window->m_wsh.isWinChanges())
window->m_wsh.accept();
else
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
break;
case WM_MBUTTONUP:
@@ -1037,6 +1049,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
case WM_MOUSEMOVE:
if(window->m_wsh.isWinChanges())
window->m_wsh.updateWindowSize();
else
event = processCursorEvent(GHOST_kEventCursorMove, window);
break;
case WM_MOUSEWHEEL:
@@ -1105,6 +1120,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
/* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
if(LOWORD(wParam)==WA_INACTIVE)
window->lostMouseCapture();
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
break;
}
@@ -1235,6 +1253,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* In GHOST, we let DefWindowProc call the timer callback.
*/
break;
case WM_CANCELMODE:
if(window->m_wsh.isWinChanges())
window->m_wsh.cancel();
}
}
else {

View File

@@ -272,6 +272,9 @@ GHOST_WindowWin32::GHOST_WindowWin32(
// Store a pointer to this class in the window structure
::SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG_PTR) this);
m_wsh.setHWND(m_hWnd);
m_wsh.setMinSize(320, 240);
// Store the device context
m_hDC = ::GetDC(m_hWnd);

View File

@@ -38,6 +38,7 @@
#endif // WIN32
#include "GHOST_Window.h"
#include "GHOST_SizerWin32.h"
#include "GHOST_TaskbarWin32.h"
#define _WIN32_WINNT 0x501 // require Windows XP or newer
@@ -280,6 +281,8 @@ public:
GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;}
GHOST_SizerWin32 m_wsh;
protected:
GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd);