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:
@@ -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)
|
||||
|
202
intern/ghost/intern/GHOST_SizerWin32.cpp
Normal file
202
intern/ghost/intern/GHOST_SizerWin32.cpp
Normal 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__*/
|
61
intern/ghost/intern/GHOST_SizerWin32.h
Normal file
61
intern/ghost/intern/GHOST_SizerWin32.h
Normal 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__*/
|
@@ -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,7 +1026,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
window->registerMouseClickEvent(1);
|
||||
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
|
||||
if(window->m_wsh.isWinChanges())
|
||||
window->m_wsh.accept();
|
||||
else
|
||||
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
window->registerMouseClickEvent(1);
|
||||
@@ -1037,7 +1049,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
}
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
event = processCursorEvent(GHOST_kEventCursorMove, window);
|
||||
if(window->m_wsh.isWinChanges())
|
||||
window->m_wsh.updateWindowSize();
|
||||
else
|
||||
event = processCursorEvent(GHOST_kEventCursorMove, window);
|
||||
break;
|
||||
case WM_MOUSEWHEEL:
|
||||
/* The WM_MOUSEWHEEL message is sent to the focus window
|
||||
@@ -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 {
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user