#ifndef WX_PRECOMP
#include <windows.h>
#include "wx/msw/winundef.h"
+ #include "wx/window.h"
#include "wx/accel.h"
#include "wx/setup.h"
#include "wx/menu.h"
#include <string.h>
-#ifndef __GNUWIN32__
+#if !defined(__GNUWIN32__)|| defined(wxUSE_NORLANDER_HEADERS)
#include <shellapi.h>
#include <mmsystem.h>
#endif
#include <windowsx.h>
#endif
-#if ( defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__ )
+#if ( defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__ ) || defined(wxUSE_NORLANDER_HEADERS)
#include <commctrl.h>
#endif
#ifndef __TWIN32__
#ifdef __GNUWIN32__
- #include <wx/msw/gnuwin32/extra.h>
+ #ifndef wxUSE_NORLANDER_HEADERS
+ #include <wx/msw/gnuwin32/extra.h>
+ #endif
#endif
#endif
{
if ( !::DestroyWindow(GetHwnd()) )
wxLogLastError("DestroyWindow");
- }
- // Restore old Window proc, if required and remove hWnd <-> wxWindow
- // association
- UnsubclassWin();
+ // remove hWnd <-> wxWindow association
+ wxRemoveHandleAssociation(this);
+ }
}
// real construction (Init() must have been called before!)
{
wxCHECK_MSG( parent, FALSE, _T("can't create wxWindow without parent") );
- CreateBase(parent, id, pos, size, style, name);
+ if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
+ return FALSE;
parent->AddChild(this);
// want everything: i.e. all keys and WM_CHAR message
m_lDlgCode = DLGC_WANTARROWS | DLGC_WANTCHARS |
DLGC_WANTTAB | DLGC_WANTMESSAGE;
-
}
MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL,
wxASSERT_MSG( hFont, _T("should have valid font") );
- ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE);
+ ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
}
return TRUE;
{
wxASSERT_MSG( !m_oldWndProc, _T("subclassing window twice?") );
- wxAssociateWinWithHandle((HWND)hWnd, this);
+ HWND hwnd = (HWND)hWnd;
+ wxCHECK_RET( ::IsWindow(hwnd), _T("invalid HWND in SubclassWin") );
- m_oldWndProc = (WXFARPROC) GetWindowLong((HWND) hWnd, GWL_WNDPROC);
- SetWindowLong((HWND) hWnd, GWL_WNDPROC, (LONG) wxWndProc);
+ wxAssociateWinWithHandle(hwnd, this);
+
+ m_oldWndProc = (WXFARPROC) GetWindowLong(hwnd, GWL_WNDPROC);
+ SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc);
}
void wxWindow::UnsubclassWin()
wxRemoveHandleAssociation(this);
// Restore old Window proc
- if ( GetHwnd() )
+ HWND hwnd = GetHwnd();
+ if ( hwnd )
{
- FARPROC farProc = (FARPROC) GetWindowLong(GetHwnd(), GWL_WNDPROC);
+ m_hWnd = 0;
+
+ wxCHECK_RET( ::IsWindow(hwnd), _T("invalid HWND in UnsubclassWin") );
+
+ FARPROC farProc = (FARPROC) GetWindowLong(hwnd, GWL_WNDPROC);
if ( (m_oldWndProc != 0) && (farProc != (FARPROC) m_oldWndProc) )
{
- SetWindowLong(GetHwnd(), GWL_WNDPROC, (LONG) m_oldWndProc);
+ SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc);
m_oldWndProc = 0;
}
-
- m_hWnd = 0;
}
}
// Determines whether native 3D effects or CTL3D should be used,
// applying a default border style if required, and returning an extended
// style to pass to CreateWindowEx.
-WXDWORD wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle, bool *want3D)
+WXDWORD wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle,
+ bool *want3D) const
{
// If matches certain criteria, then assume no 3D effects
// unless specifically requested (dealt with in MakeExtendedStyle)
// We may be faking the client origin. So a window that's really at (0,
// 30) may appear (to wxWin apps) to be at (0, 0).
- if ( parent )
- {
- wxPoint pt(parent->GetClientAreaOrigin());
- point.x -= pt.x;
- point.y -= pt.y;
- }
+ wxPoint pt(parent->GetClientAreaOrigin());
+ point.x -= pt.x;
+ point.y -= pt.y;
}
if ( x )
*y = rect.bottom;
}
+// set the size of the window: if the dimensions are positive, just use them,
+// but if any of them is equal to -1, it means that we must find the value for
+// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
+// which case -1 is a valid value for x and y)
+//
+// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
+// the width/height to best suit our contents, otherwise we reuse the current
+// width/height
void wxWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
+ // get the current size and position...
int currentX, currentY;
GetPosition(¤tX, ¤tY);
int currentW,currentH;
GetSize(¤tW, ¤tH);
- if ( x == currentX && y == currentY && width == currentW && height == currentH )
+ // ... and don't do anything (avoiding flicker) if it's already ok
+ if ( x == currentX && y == currentY &&
+ width == currentW && height == currentH )
+ {
return;
+ }
- int actualWidth = width;
- int actualHeight = height;
- int actualX = x;
- int actualY = y;
if ( x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
- actualX = currentX;
+ x = currentX;
if ( y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
- actualY = currentY;
+ y = currentY;
- AdjustForParentClientOrigin(actualX, actualY, sizeFlags);
+ AdjustForParentClientOrigin(x, y, sizeFlags);
+ wxSize size(-1, -1);
if ( width == -1 )
- actualWidth = currentW;
+ {
+ if ( sizeFlags && wxSIZE_AUTO_WIDTH )
+ {
+ size = DoGetBestSize();
+ width = size.x;
+ }
+ else
+ {
+ // just take the current one
+ width = currentW;
+ }
+ }
+
if ( height == -1 )
- actualHeight = currentH;
+ {
+ if ( sizeFlags && wxSIZE_AUTO_HEIGHT )
+ {
+ if ( size.x == -1 )
+ {
+ size= DoGetBestSize();
+ }
+ //else: already called DoGetBestSize() above
- HWND hWnd = GetHwnd();
- if ( hWnd )
- MoveWindow(hWnd, actualX, actualY, actualWidth, actualHeight, (BOOL)TRUE);
+ height = size.y;
+ }
+ else
+ {
+ // just take the current one
+ height = currentH;
+ }
+ }
+
+ if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) )
+ {
+ wxLogLastError("MoveWindow");
+ }
+}
+
+// for a generic window there is no natural best size - just use the current one
+wxSize wxWindow::DoGetBestSize()
+{
+ return GetSize();
}
void wxWindow::DoSetClientSize(int width, int height)
SIZE sizeRect;
TEXTMETRIC tm;
- GetTextExtentPoint(dc, (const wxChar *)string, (int)string.Length(), &sizeRect);
+ GetTextExtentPoint(dc, string, (int)string.Length(), &sizeRect);
GetTextMetrics(dc, &tm);
if ( fontToUse && fnt && hfontOld )
ReleaseDC(hWnd, dc);
- if ( x ) *x = sizeRect.cx;
- if ( y ) *y = sizeRect.cy;
- if ( descent ) *descent = tm.tmDescent;
- if ( externalLeading ) *externalLeading = tm.tmExternalLeading;
+ if ( x )
+ *x = sizeRect.cx;
+ if ( y )
+ *y = sizeRect.cy;
+ if ( descent )
+ *descent = tm.tmDescent;
+ if ( externalLeading )
+ *externalLeading = tm.tmExternalLeading;
}
#if wxUSE_CARET && WXWIN_COMPATIBILITY
}
#endif // wxUSE_CARET
+// ---------------------------------------------------------------------------
+// popup menu
+// ---------------------------------------------------------------------------
+
+bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
+{
+ menu->SetInvokingWindow(this);
+ menu->UpdateUI();
+
+ HWND hWnd = GetHwnd();
+ HMENU hMenu = GetHmenuOf(menu);
+ POINT point;
+ point.x = x;
+ point.y = y;
+ ::ClientToScreen(hWnd, &point);
+ wxCurrentPopupMenu = menu;
+ ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
+ wxYield();
+ wxCurrentPopupMenu = NULL;
+
+ menu->SetInvokingWindow(NULL);
+
+ return TRUE;
+}
+
// ===========================================================================
// pre/post message processing
// ===========================================================================
// buttons want process Enter themselevs
bProcess = FALSE;
}
- // else: but if it does not it makes sense to make it
- // work like a TAB - and that's what we do.
- // Note that Ctrl-Enter always works this way.
+ else
+ {
+ wxPanel *panel = wxDynamicCast(this, wxPanel);
+ wxButton *btn = NULL;
+ if ( panel )
+ {
+ // panel may have a default button which should
+ // be activated by Enter
+ btn = panel->GetDefaultItem();
+ }
+
+ if ( btn && btn->IsEnabled() )
+ {
+ // if we do have a default button, do press it
+ btn->MSWCommand(BN_CLICKED, 0 /* unused */);
+
+ return TRUE;
+ }
+ // else: but if it does not it makes sense to make
+ // it work like a TAB - and that's what we do.
+ // Note that Ctrl-Enter always works this way.
+ }
}
break;
bool wxWindow::MSWTranslateMessage(WXMSG* pMsg)
{
- return m_acceleratorTable.Ok() &&
- ::TranslateAccelerator(GetHwnd(),
- GetTableHaccel(m_acceleratorTable),
- (MSG *)pMsg);
+ return m_acceleratorTable.Translate(this, pMsg);
}
// ---------------------------------------------------------------------------
// it with wxWindow stored in wxWndHook
if ( !wnd && wxWndHook )
{
+#if 0 // def __WXDEBUG__
+ char buf[512];
+ ::GetClassNameA((HWND) hWnd, buf, 512);
+ wxString className(buf);
+#endif
+
wxAssociateWinWithHandle(hWnd, wxWndHook);
wnd = wxWndHook;
wxWndHook = NULL;
case WM_MBUTTONUP:
case WM_MBUTTONDBLCLK:
{
- int x = LOWORD(lParam);
- int y = HIWORD(lParam);
+ short x = LOWORD(lParam);
+ short y = HIWORD(lParam);
processed = HandleMouseEvent(message, x, y, wParam);
}
return (wxWindow *)node->Data();
}
+#if 0 // def __WXDEBUG__
+static int gs_AssociationCount = 0;
+#endif
+
void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win)
{
// adding NULL hWnd is (first) surely a result of an error and
wxCHECK_RET( hWnd != (HWND)NULL,
_T("attempt to add a NULL hWnd to window list ignored") );
- if ( !wxWinHandleList->Find((long)hWnd) )
+
+ wxWindow *oldWin = wxFindWinFromHandle((WXHWND) hWnd);
+ if ( oldWin && (oldWin != win) )
+ {
+ wxString str(win->GetClassInfo()->GetClassName());
+ wxLogError("Bug! Found existing HWND %X for new window of class %s", (int) hWnd, (const char*) str);
+ }
+ else if (!oldWin)
+ {
+#if 0 // def __WXDEBUG__
+ gs_AssociationCount ++;
+ wxLogDebug("+ Association %d", gs_AssociationCount);
+#endif
+
wxWinHandleList->Append((long)hWnd, win);
+ }
}
void wxRemoveHandleAssociation(wxWindow *win)
{
+#if 0 // def __WXDEBUG__
+ if (wxWinHandleList->Member(win))
+ {
+ wxLogDebug("- Association %d", gs_AssociationCount);
+ gs_AssociationCount --;
+ }
+#endif
wxWinHandleList->DeleteObject(win);
}
if ( style & WS_CHILD )
controlId = id;
+ wxString className(wclass);
+ if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
+ {
+ className += _T("NR");
+ }
+
m_hWnd = (WXHWND)CreateWindowEx(extendedStyle,
wclass,
title ? title : _T(""),
}
wxWndHook = NULL;
- wxWinHandleList->Append((long)m_hWnd, this);
+#ifdef __WXDEBUG__
+ wxNode* node = wxWinHandleList->Member(this);
+ if (node)
+ {
+ HWND hWnd = (HWND) node->GetKeyInteger();
+ if (hWnd != (HWND) m_hWnd)
+ {
+ wxLogError("A second HWND association is being added for the same window!");
+ }
+ }
+#endif
+ wxAssociateWinWithHandle((HWND) m_hWnd, this);
return TRUE;
}
SelectObject(dc,was);
}
ReleaseDC((HWND)wnd, dc);
- *x = tm.tmAveCharWidth;
- *y = tm.tmHeight + tm.tmExternalLeading;
+
+ if ( x )
+ *x = tm.tmAveCharWidth;
+ if ( y )
+ *y = tm.tmHeight + tm.tmExternalLeading;
// if ( the_font )
// the_font->ReleaseResource();
{
wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
+
#if defined(__WIN32__) && !defined(__TWIN32__)
GetCurrentThreadId());
// (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
#else
- GetCurrentTask());
+ GetCurrentTask());
#endif
}
else