#include "awt_event.h"
#include "awt_window.h"
#include "awt_palette.h"
#include "awt_toolkit.h"
#include "awt_defs.h"
#ifdef INTLUNICODE
#include "awt_wcompstr.h"
#endif
// All java header files are extern "C"
extern "C" {
#include "java_awt_Component.h"
#include "java_awt_Insets.h"
#include "java_awt_Event.h"
#include "sun_awt_windows_WComponentPeer.h"
};
HHOOK AwtWindow::m_hKeyboardHook = (HHOOK)NULL;
UINT AwtWindow::m_nHookCount = 0;
ATOM AwtWindow::thisPtr = 0;
#if !defined(_WIN32)
ATOM AwtWindow::thisLow = 0;
#endif
AwtWindow::AwtWindow(JHandle *peer) : AwtComponent(peer)
{
m_pMsg = NULL;
m_hWnd = NULL;
m_PrevWndProc = NULL;
if (AwtWindow::thisPtr == 0) {
AwtWindow::RegisterAtoms();
}
}
// -----------------------------------------------------------------------
//
// Default hInst parameter to ::CreateWindow
//
// -----------------------------------------------------------------------
HINSTANCE
AwtWindow::WindowHInst()
{
return ::GetModuleHandle(__awt_dllName);
}
// -----------------------------------------------------------------------
//
// The AwtComponent is being destroyed.
//
// Destroy the native window if it still exists.
//
// -----------------------------------------------------------------------
AwtWindow::~AwtWindow()
{
if (m_hWnd) {
Destroy(m_hWnd);
}
}
// -----------------------------------------------------------------------
//
// Create a Windows widget for an AwtWindow component
//
// This method MUST be executed on the "main gui thread". Since this
// method is ALWAYS executed on the same thread no locking is necessary.
//
// -----------------------------------------------------------------------
void AwtWindow::CreateWidget(HWND hwndParent)
{
Hjava_awt_Component *target;
#ifdef _WIN32
//
// Switch to the "main gui thread" if necessary... This method must
// be executed on the "gui thread" because it creates a window...
//
if (! AwtToolkit::theToolkit->IsGuiThread()) {
AwtMethodInfo info(this, AwtComponent::CREATE, (long)hwndParent);
AwtToolkit::theToolkit->CallAwtMethod( &info );
return;
}
#endif
//
// This method is now being executed on the "main gui thread"
//
ASSERT( AwtToolkit::theToolkit->IsGuiThread() );
target = (Hjava_awt_Component *)
unhand((HWComponentPeer *)m_pJavaPeer)->target;
CHECK_NULL( target, "Target is null." );
//
// Create the new window
//
#ifdef _WIN32
m_hWnd = ::CreateWindowEx(WindowExStyle(),
#else
m_hWnd = ::CreateWindow(
#endif
WindowClass(),
"",
WindowStyle(),
(int) unhand(target)->x,
(int) unhand(target)->y,
(int) unhand(target)->width,
(int) unhand(target)->height,
hwndParent,
NULL,
WindowHInst(),
NULL);
//
// Subclass the window to allow windows events to be intercepted...
//
ASSERT( ::IsWindow(m_hWnd) );
SubclassWindow(TRUE);
}
// -----------------------------------------------------------------------
//
// Destroy a Windows widget for an AwtWindow component
//
// This method MUST be executed on the "main gui thread". Since this
// method is ALWAYS executed on the same thread no locking is necessary.
//
// -----------------------------------------------------------------------
void AwtWindow::Destroy(HWND hWnd)
{
#ifdef _WIN32
//
// Switch to the "main gui thread" if necessary... This method must
// be executed on the "gui thread" because it creates a window...
//
if (! AwtToolkit::theToolkit->IsGuiThread()) {
AwtMethodInfo info(this, AwtComponent::DESTROY, (long)hWnd);
AwtToolkit::theToolkit->CallAwtMethod( &info );
return;
}
#endif
ASSERT( ::IsWindow(hWnd) );
::DestroyWindow(hWnd);
}
// -----------------------------------------------------------------------
//
// This is a callback from java to ask to process a specific event.
// The original message as coming from windows is in JavaEventInfo::m_msg.
//
// -----------------------------------------------------------------------
void AwtWindow::HandleEvent(JavaEventInfo* pInfo, Event *pEvent)
{
long modifiers = pEvent->modifiers;
MSG* pMsg = &(pInfo->m_msg);
if ((pMsg == NULL) || (pMsg->message == 0)) {
return;
}
#ifdef _WIN32
//
// Switch to the "main gui thread" if necessary... This method must
// be executed on the "gui thread" because it directly calls the
// Window procedure of the window...
//
if (! AwtToolkit::theToolkit->IsGuiThread()) {
AwtMethodInfo info(this, AwtComponent::HANDLE_EVENT, (long)pInfo, (long)pEvent);
AwtToolkit::theToolkit->CallAwtMethod( &info );
return;
}
//
// This method is now being executed on the "main gui thread"
//
ASSERT( AwtToolkit::theToolkit->IsGuiThread() );
#endif
// Reset the keyboard state momentarily as long as the keyboard
// message is being handled and then reset the keyboard state to the
// current state. This allows the java client app to override the
// modifiers before they are handled by the control.
BYTE keyState[256];
::GetKeyboardState(keyState);
// reset modifiers keys if java is asking so
if (modifiers & java_awt_Event_CTRL_MASK)
{
m_keyState[VK_CONTROL] |= 0x80;
}
else
{
m_keyState[VK_CONTROL] = 0;
}
if(modifiers & java_awt_Event_SHIFT_MASK)
{
m_keyState[VK_SHIFT] |= 0x80;
}
else
{
m_keyState[VK_SHIFT] = 0;
}
// java_awt_Event_ALT_MASK is used either to signal an alt key
// and/or the middle mouse button pressed
if(modifiers & java_awt_Event_ALT_MASK)
{
m_keyState[VK_MBUTTON] |= 0x80;
m_keyState[VK_MENU] |= 0x80;
}
else
{
m_keyState[VK_MBUTTON] = 0;
m_keyState[VK_MENU] = 0;
}
if(modifiers & java_awt_Event_META_MASK)
{
m_keyState[VK_RBUTTON] |= 0x80;
}
else
{
m_keyState[VK_RBUTTON] = 0;
}
// in case we are processing a key event we check to see if the ascii code is
// the same we passed into java. If so, java didn't change the key (maybe the modifiers
// but we just handled that case) so just keep going and use the value cached in the hook proc.
// This cover the <ctrl>C problem in win95. When <ctrl>C is received VkKeyScan (in JavaEventInfo::JavaCharToWindows)
// cannot backup the ascii value to the original virtual-key.
// (java uses ascii so we call ToAscii in AwtWindow::TranslateToAscii).
// This is not a problem in NT (since copy still works) but screw 95 up (we don't get WM_CHAR and
// so WM_COPY).
// If the value is different java did change the value so call JavaEventInfo::JavaCharToWindows
// to figure out what character we have.
switch (pEvent->id)
{
case java_awt_Event_KEY_EVENT:
case java_awt_Event_KEY_PRESS:
case java_awt_Event_KEY_RELEASE:
case java_awt_Event_KEY_ACTION:
case java_awt_Event_KEY_ACTION_RELEASE:
if (pInfo->m_arg3 != pEvent->key)
pMsg->wParam = JavaEventInfo::JavaCharToWindows(pEvent->key, m_keyState);
break;
}
::SetKeyboardState(m_keyState);
//
// Key-down messages are intercepted by a keyboard-hook when they
// are removed from the message queue via ::GetMessage().
//
if (pMsg->message == WM_KEYDOWN)
{
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
}
else if (m_PrevWndProc)
{
(void)::CallWindowProc(m_PrevWndProc, pMsg->hwnd,
pMsg->message, pMsg->wParam, pMsg->lParam);
}
::SetKeyboardState(keyState);
}
// -----------------------------------------------------------------------
//
// Show / Hide the window...
//
// -----------------------------------------------------------------------
void AwtWindow::Show(BOOL bState)
{
ASSERT( ::IsWindow(m_hWnd) );
if (bState) {
::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
}
else
::ShowWindow(m_hWnd, SW_HIDE);
}
// -----------------------------------------------------------------------
//
// Enable / Disable the window...
//
// -----------------------------------------------------------------------
void AwtWindow::Enable(BOOL bState)
{
ASSERT( ::IsWindow(m_hWnd) );
::EnableWindow(m_hWnd, bState);
}
// -----------------------------------------------------------------------
//
// Set the font for the window...
//
// -----------------------------------------------------------------------
BOOL AwtWindow::SetFont(AwtFont* font)
{
BOOL bStatus;
bStatus = AwtComponent::SetFont(font);
if (font && bStatus) {
#ifdef INTLUNICODE
::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)font->GetFontForEncoding(this->GetPrimaryEncoding()),
MAKELPARAM(TRUE, 0));
#else // INTLUNICODE
::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)font->GetFont(),
MAKELPARAM(TRUE, 0));
#endif // INTLUNICODE
}
return bStatus;
}
// -----------------------------------------------------------------------
//
// Move and resize the window...
//
// -----------------------------------------------------------------------
void AwtWindow::Reshape(long x, long y, long width, long height)
{
HWND hwnd;
ASSERT( ::IsWindow(m_hWnd) );
RECT rcParent, rcWindow;
// the coordinates are in parent coordinates.
// so if this is not a top level window convert the coordinates
//if ((hwnd = ::GetWindow(m_hWnd, GW_OWNER))) {
// ::GetWindowRect(hwnd, &rcParent);
// x += rcParent.left;
// y += rcParent.top;
//}
//else if ((hwnd = ::GetParent(m_hWnd))) {
if (::GetWindow(m_hWnd, GW_OWNER) == NULL) {
if ((hwnd = ::GetParent(m_hWnd))) {
::GetWindowRect(hwnd, &rcParent);
::GetClientRect(hwnd, &rcWindow);
::MapWindowPoints(hwnd, NULL, (LPPOINT)&rcWindow, 2);
//if (::GetWindow(m_hWnd, GW_OWNER) == NULL) {
x -= rcWindow.left - rcParent.left;
y -= rcWindow.top - rcParent.top;
//}
}
//else if ((hwnd = ::GetWindow(m_hWnd, GW_OWNER))) {
// ::GetWindowRect(hwnd, &rcParent);
// x += rcParent.left;
// y += rcParent.top;
//}
}
VERIFY( ::SetWindowPos(m_hWnd, NULL, x, y, width, height,
SWP_NOZORDER | SWP_NOACTIVATE) );
}
// -----------------------------------------------------------------------
//
// Give this component the input focus...
//
// -----------------------------------------------------------------------
void AwtWindow::GetFocus(void)
{
#ifdef _WIN32
//
// Switch to the "main gui thread" if necessary... This method must
// be executed on the "gui thread"...
//
if (! AwtToolkit::theToolkit->IsGuiThread()) {
AwtMethodInfo info(this, AwtComponent::GET_FOCUS);
AwtToolkit::theToolkit->CallAwtMethod( &info );
return;
}
#endif
ASSERT( ::IsWindow(m_hWnd) );
::SetFocus(m_hWnd);
}
// -----------------------------------------------------------------------
//
// Return the component that should receive the input focus.
//
// -----------------------------------------------------------------------
AwtComponent* AwtWindow::NextFocus(void)
{
ASSERT(0);
return NULL;
}
//-------------------------------------------------------------------------
//
// Return the "windows" window handle
//
//-------------------------------------------------------------------------
HWND AwtWindow::GetWindowHandle(void)
{
ASSERT( ::IsWindow(m_hWnd) );
return m_hWnd;
}
//-------------------------------------------------------------------------
//
// Return true if it doesn't have the focus. This function is also
// implemented in windows controls and it always returns false because
// windows handle the focus correctly there
//
//-------------------------------------------------------------------------
BOOL AwtWindow::WantFocusOnMouseDown()
{
return ((m_hWnd == ::GetFocus()) ? FALSE : TRUE);
}
//-------------------------------------------------------------------------
//
// Capture the mouse so that mouse events get re-direct to the
// proper component. This allow MouseDrag to work correctly and
// MouseUp to be sent to the component which received the muose down
//
//-------------------------------------------------------------------------
void AwtWindow::CaptureMouse(AwtButtonType button, UINT metakeys)
{
// capture the mouse if it was not captured already
// increment the counter so that if a left/right click
// occurs while a right/left button is pressed already
// we don't realese too soon
if (!m_nCaptured++)
::SetCapture(m_hWnd);
}
//-------------------------------------------------------------------------
//
// Release the mouse if the counter reaches zero. We need a counter so
// that if a second button get pressed while the other is pressed already
// we are still able to send MouseUp to the right component
//
//-------------------------------------------------------------------------
BOOL AwtWindow::ReleaseMouse(AwtButtonType button, UINT metakeys, int x, int y)
{
if (m_nCaptured && !--m_nCaptured)
::ReleaseCapture();
// defproc process the message
return FALSE;
}
// -----------------------------------------------------------------------
//
//
// -----------------------------------------------------------------------
MSG * AwtWindow::GetCurrentMessage(void)
{
ASSERT( AwtToolkit::theToolkit->IsGuiThread() );
return m_pMsg;
}
// -----------------------------------------------------------------------
//
// Subclass (or remove the subclass from) this component's window
//
// -----------------------------------------------------------------------
void AwtWindow::SubclassWindow(BOOL bState)
{
ASSERT( ::IsWindow(m_hWnd) );
if (bState) {
SetThisPtr(m_hWnd, this);
//
// Subclass the window
//
m_PrevWndProc = (WNDPROC)::SetWindowLong(m_hWnd, GWL_WNDPROC,
(LONG)AwtWindow::WndProc);
ASSERT(m_PrevWndProc);
//
// Install the Keyboard hook if this is the first time a window
// is being subclassed...
//
if (m_nHookCount++ == 0) {
m_hKeyboardHook =
::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)AwtWindow::KeyHook,
::GetModuleHandle(__awt_dllName),
#ifdef _WIN32
AwtToolkit::theToolkit->GetGuiThreadId()
#else
::GetCurrentTask()
#endif
);
}
}
else {
//
// Remove the Keyboard hook if this is the last window being
// "un-subclassed"...
//
if (--m_nHookCount == 0) {
VERIFY( ::UnhookWindowsHookEx(m_hKeyboardHook) );
m_hKeyboardHook = NULL;
}
(void) ::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_PrevWndProc);
m_PrevWndProc = NULL;
RemoveThisPtr(m_hWnd);
}
}
// -----------------------------------------------------------------------
//
// Register the atom(s) used to attach the "this pointer" of the C++ object
// to the window of the widget...
//
// -----------------------------------------------------------------------
void AwtWindow::RegisterAtoms(void)
{
if (AwtWindow::thisPtr == 0) {
AwtWindow::thisPtr = ::GlobalAddAtom("ThisPtr");
#if !defined(_WIN32)
AwtWindow::thisLow = ::GlobalAddAtom("ThisLow");
#endif
}
}
// -----------------------------------------------------------------------
//
// Remove all registered atoms
//
// -----------------------------------------------------------------------
void AwtWindow::UnRegisterAtoms(void)
{
::GlobalDeleteAtom(AwtWindow::thisPtr);
#if !defined(_WIN32)
::GlobalDeleteAtom(AwtWindow::thisLow);
#endif
}
// -----------------------------------------------------------------------
//
// Associate the "this pointer" of an AwtComponent with a window handle
//
// -----------------------------------------------------------------------
void AwtWindow::SetThisPtr(HWND hWnd, AwtWindow* pThis)
{
ASSERT( ::IsWindow(hWnd) );
#if defined(_WIN32 )
::SetProp(hWnd, MAKEINTATOM(AwtWindow::thisPtr), (HANDLE)pThis);
#else
::SetProp(hWnd, MAKEINTATOM(AwtWindow::thisPtr), (HANDLE)HIWORD(pThis));
::SetProp(hWnd, MAKEINTATOM(AwtWindow::thisLow), (HANDLE)LOWORD(pThis));
#endif
}
// -----------------------------------------------------------------------
//
// Return the "this pointer" of the AwtComponent which corresponds to the
// given window handle.
//
// -----------------------------------------------------------------------
AwtWindow* AwtWindow::GetThisPtr(HWND hWnd)
{
void* pThis = NULL;
if (hWnd) {
ASSERT( ::IsWindow(hWnd) );
#if defined(_WIN32 )
pThis = (void*)::GetProp(hWnd, MAKEINTATOM(AwtWindow::thisPtr));
#else
WORD thisHi, thisLo;
thisHi = (WORD) ::GetProp(hWnd, MAKEINTATOM(AwtWindow::thisPtr));
thisLo = (WORD) ::GetProp(hWnd, MAKEINTATOM(AwtWindow::thisLow));
pThis = MAKELP(thisHi, thisLo);
#endif
}
return (AwtWindow *)pThis;
}
// -----------------------------------------------------------------------
//
// Remove the "this pointer" from the given window handle
//
// -----------------------------------------------------------------------
void AwtWindow::RemoveThisPtr(HWND hWnd)
{
ASSERT( ::IsWindow(hWnd) );
#if defined(_WIN32 )
::RemoveProp(hWnd, MAKEINTATOM(AwtWindow::thisPtr));
#else
::RemoveProp(hWnd, MAKEINTATOM(AwtWindow::thisPtr));
::RemoveProp(hWnd, MAKEINTATOM(AwtWindow::thisLow));
#endif
}
// -----------------------------------------------------------------------
//
//
// -----------------------------------------------------------------------
LRESULT AWT_CALLBACK AwtWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
MSG msg;
DWORD pos;
LRESULT result = 0;
AwtWindow* pThis = AwtWindow::GetThisPtr(hWnd);
ASSERT( pThis );
if (pThis) {
//
// Save the DefWindowProc pointer in a local variable, since it will
// be lost when a WM_DESTROY message is processed...
//
WNDPROC DefProc = pThis->m_PrevWndProc;
//
// Copy the current windows message into a termporary MSG structure...
// This structure can be accessed via the GetCurrentMessage() method.
//
pos = ::GetMessagePos();
msg.hwnd = hWnd;
msg.message = message;
msg.wParam = wParam;
msg.lParam = lParam;
msg.time = ::GetMessageTime();
msg.pt.x = (int)(short)LOWORD(pos);
msg.pt.y = (int)(short)HIWORD(pos);
pThis->m_pMsg = &msg;
if (pThis->Dispatch(message, wParam, lParam, &result) == FALSE) {
result = ::CallWindowProc(DefProc, hWnd, message, wParam, lParam);
}
// Clear the cached MSG pointer
pThis->m_pMsg = NULL;
}
return result;
}
// -----------------------------------------------------------------------
//
//
// -----------------------------------------------------------------------
LRESULT AWT_CALLBACK AwtWindow::KeyHook(int code, WPARAM wParam, LPARAM lParam)
{
LRESULT ret = 0;
if (code == HC_ACTION) {
HWND hWnd = ::GetFocus();
AwtWindow* pThis = AwtWindow::GetThisPtr(hWnd);
BOOL bIsKeyDown = ! (lParam & 0x80000000L);
if (/*bIsKeyDown &&*/ pThis) {
MSG msg;
DWORD pos;
UINT scanCode = HIWORD(lParam) & 0xFF;
//
// Copy the current windows message into a termporary MSG
// structure... This structure can be accessed via the
// AwtComponent::GetCurrentMessage() method.
//
pos = ::GetMessagePos();
msg.hwnd = hWnd;
msg.message = (bIsKeyDown ? WM_KEYDOWN : WM_KEYUP);
msg.wParam = wParam;
msg.lParam = lParam;
msg.time = ::GetMessageTime();
msg.pt.x = (int)(short)LOWORD(pos);
msg.pt.y = (int)(short)HIWORD(pos);
pThis->m_pMsg = &msg;
// Is the key being released or pressed?
if (bIsKeyDown) {
ret = pThis->OnKeyDown(wParam, scanCode);
} else {
ret = pThis->OnKeyUp(wParam, scanCode);
}
// Clear the cached MSG pointer.
pThis->m_pMsg = NULL;
} else {
ret = ::CallNextHookEx(m_hKeyboardHook, code, wParam, lParam);
}
}
return ret;
}
// -----------------------------------------------------------------------
//
//
// -----------------------------------------------------------------------
BOOL AwtWindow::Dispatch(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT * result)
{
AwtComponent *pControl;
BOOL bRet = FALSE;
*result = 0;
switch( msg ) {
case WM_CLOSE:
bRet = OnClose();
break;
case WM_DESTROY:
bRet = OnDestroy();
break;
case WM_PAINT: {
RECT r;
::GetUpdateRect(m_hWnd, &r, FALSE);
bRet = OnPaint((HDC)wParam, r.left, r.top,
(r.right-r.left), (r.bottom - r.top));
break;
}
case WM_ERASEBKGND:
bRet = OnEraseBackground((HDC)wParam);
// If the message has been handled, then return non-zero
*result = bRet;
break;
case WM_COMMAND:
#ifdef _WIN32
pControl = AwtWindow::GetThisPtr( (HWND)lParam );
// when WM_COMMAND comes in from menu there is no lParam
// and so no object is able to receive the OnCommand.
// In this, since we know it is a menu, we call OnSelect
// on this
if (pControl) {
bRet = pControl->OnCommand( HIWORD(wParam), LOWORD(wParam) );
}
else if (HIWORD(wParam) == 0) {
// this is a menu, so notify the owner
OnSelect(LOWORD(wParam));
}
#else
pControl = AwtWindow::GetThisPtr( (HWND)LOWORD(lParam) );
if (pControl) {
bRet = pControl->OnCommand( HIWORD(lParam), wParam );
}
else if (HIWORD(lParam) == 0) {
// this is a menu, so notify the owner
OnSelect(wParam);
}
#endif
// Return 0 if the command was handled...
*result = !bRet;
break;
#ifdef _WIN32
case WM_CTLCOLOREDIT:
case WM_CTLCOLORBTN:
case WM_CTLCOLORSTATIC:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORSCROLLBAR:
pControl = AwtWindow::GetThisPtr( (HWND)lParam );
#else
case WM_CTLCOLOR:
pControl = AwtWindow::GetThisPtr( (HWND)LOWORD(lParam) );
#endif
if (pControl) {
bRet = pControl->OnCtlColor( (HDC)wParam );
if (bRet) {
*result = (LRESULT)pControl->GetColor(Background)->GetBrush();
}
}
break;
case WM_SIZE:
{
RECT rc;
::GetWindowRect(m_hWnd, &rc);
// the coordinates has to be the parent coordinates.
// so if this is not a top level window convert the coordinates
//HWND hwnd = ::GetParent(m_hWnd);
//if (!hwnd)
// hwnd = ::GetWindow(m_hWnd, GW_OWNER);
//if (hwnd) {
// RECT rcParent;
// ::GetWindowRect(hwnd, &rcParent);
// rc.left -= rcParent.left;
// rc.top -= rcParent.top;
// rc.right -= rcParent.left;
// rc.bottom -= rcParent.top;
//}
bRet = OnSize( (UINT)wParam, rc.right - rc.left, rc.bottom - rc.top);
// If the message has been handled, then return zero
*result = ! bRet;
break;
}
case WM_MOVE:
{
RECT rc;
::GetWindowRect(m_hWnd, &rc);
bRet = OnMove(rc.left, rc.top);
break;
}
case WM_LBUTTONDOWN:
bRet = OnMouseDown(AwtLeftButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_LBUTTONUP:
bRet = OnMouseUp(AwtLeftButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_LBUTTONDBLCLK:
bRet = OnMouseDblClick(AwtLeftButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_RBUTTONDOWN:
bRet = OnMouseDown(AwtRightButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_RBUTTONUP:
bRet = OnMouseUp(AwtRightButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_RBUTTONDBLCLK:
bRet = OnMouseDblClick(AwtRightButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_MBUTTONDOWN:
bRet = OnMouseDown(AwtMiddleButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_MBUTTONUP:
bRet = OnMouseUp(AwtMiddleButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_MBUTTONDBLCLK:
bRet = OnMouseDblClick(AwtMiddleButton, wParam,
(short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case WM_MOUSEMOVE: {
AwtButtonType button = AwtNoButton;
if (wParam & MK_LBUTTON) button = AwtLeftButton;
else if (wParam & MK_MBUTTON) button = AwtMiddleButton;
else if (wParam & MK_RBUTTON) button = AwtRightButton;
bRet = OnMouseMove(button, wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
break;
}
// case WM_KEYDOWN:
// bRet = OnKeyDown(wParam);
// break;
case WM_CHAR:
bRet = OnChar(wParam);
break;
// case WM_KEYUP:
// bRet = OnKeyUp(wParam, (HIWORD(lParam) & 0xFF));
// break;
case WM_SETFOCUS:
bRet = OnSetFocus();
// Return 0 if the setfocus was handled...
*result = !bRet;
break;
case WM_KILLFOCUS:
bRet = OnKillFocus();
*result = !bRet;
break;
case WM_SETCURSOR:
bRet = OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
// keep the TRUE when returned from the function
*result = bRet;
break;
case WM_HSCROLL:
#if _WIN32
bRet = OnHScroll(LOWORD(wParam), (short)HIWORD(wParam));
#else
bRet = OnHScroll(wParam, LOWORD(lParam));
#endif
//!DR this is to call OnScroll on our scroll bar implementation.
//!DR We should catch the LButtonDown and do everything on our own...
#ifdef _WIN32
pControl = AwtWindow::GetThisPtr( (HWND)lParam );
if (pControl) {
pControl->OnScroll( LOWORD(wParam), (short)HIWORD(wParam) );
}
#else
pControl = AwtWindow::GetThisPtr( (HWND)LOWORD(lParam) );
if (pControl) {
pControl->OnScroll( wParam, HIWORD(lParam));
}
#endif
break;
case WM_VSCROLL:
#if _WIN32
bRet = OnVScroll(LOWORD(wParam), (short)HIWORD(wParam));
#else
bRet = OnVScroll(wParam, LOWORD(lParam));
#endif
//!DR this is to call OnScroll on our scroll bar implementation.
//!DR We should catch the LButtonDown and do everything on our own...
#ifdef _WIN32
pControl = AwtWindow::GetThisPtr( (HWND)lParam );
if (pControl) {
pControl->OnScroll( LOWORD(wParam), (short)HIWORD(wParam) );
}
#else
pControl = AwtWindow::GetThisPtr( (HWND)LOWORD(lParam) );
if (pControl) {
pControl->OnScroll( wParam, HIWORD(lParam));
}
#endif
break;
case WM_MENUSELECT:
#ifdef _WIN32
bRet = OnMenuSelect((HMENU)lParam, (UINT) HIWORD(wParam), (UINT) LOWORD(wParam));
#else
bRet = OnMenuSelect((HMENU)HIWORD(lParam), (UINT) LOWORD(lParam), (UINT)wParam);
#endif
break;
case WM_NCHITTEST:
{
POINT pt;
pt.x = (int)(short)LOWORD(lParam);
pt.y = (int)(short)HIWORD(lParam);
bRet = OnNCHitTest(&pt, wParam);
break;
}
case WM_PALETTECHANGED:
{
HWND hwndPalChg = (HWND) wParam; // handle of window that changed palette
if( hwndPalChg == m_hWnd)
{
break;
}
// The following code is for all other windows to realize
// their palettes as background palettes when the window in
// focus gets to realize its palette as a foreground palette.
// By this all windows should have the best possible colors.
HPALETTE hPal = AwtToolkit::GetToolkitDefaultPalette()->GetPalette();
HDC hDC = ::GetDC(m_hWnd);
VERIFY(::SelectPalette(hDC, hPal, TRUE));
VERIFY(::ReleaseDC(m_hWnd, hDC));
::InvalidateRect(m_hWnd, NULL, TRUE);
::UpdateWindow(m_hWnd);
break;
}
case WM_QUERYNEWPALETTE:
{
HPALETTE hNewPal = AwtToolkit::GetToolkitDefaultPalette()->GetPalette();
HDC hDC = ::GetDC(m_hWnd);
HPALETTE hOldPal = ::SelectPalette(hDC, hNewPal, TRUE);
int i = ::RealizePalette(hDC); // Realize drawing palette.
VERIFY(::ReleaseDC(m_hWnd, hDC));
//if (i)
//{
::SelectClipRgn(hDC, NULL);
::InvalidateRect(m_hWnd, NULL, TRUE);
::UpdateWindow(m_hWnd);
//}
hDC = ::GetDC(m_hWnd);
VERIFY(::SelectPalette(hDC, hOldPal, TRUE));
VERIFY(::ReleaseDC(m_hWnd, hDC));
break;
}
#ifdef INTLUNICODE
case WM_DRAWITEM:
if(lParam)
{
LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
if(lpdis->CtlType == ODT_MENU)
bRet = OnDrawMenuItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
else
{
pControl = AwtWindow::GetThisPtr( (HWND)lpdis->hwndItem);
if (pControl) {
bRet = pControl->OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
}
}
break;
}
case WM_MEASUREITEM:
if(lParam)
{
LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam;
if(lpmis->CtlType == ODT_MENU)
bRet = OnMeasureMenuItem((UINT)wParam, (LPMEASUREITEMSTRUCT)lParam);
break;
}
case WM_DELETEITEM:
{
bRet = OnDeleteItem((UINT)wParam, (LPDELETEITEMSTRUCT)lParam);
break;
}
#endif
}
return bRet;
}
BOOL AwtWindow::OnNCHitTest(LPPOINT ppt, int nHitTest)
{
// if m_HoldMouse is not this we are moving over a different window
if (AwtToolkit::m_HoldMouse != this) {
int64 time = PR_NowMS(); // time in milliseconds
// if m_HoldMouse exists fire an exit event
if (AwtToolkit::m_HoldMouse) {
::ScreenToClient(AwtToolkit::m_HoldMouse->GetWindowHandle(), ppt);
AwtToolkit::RaiseJavaEvent(AwtToolkit::m_HoldMouse->GetPeer(),
AwtEventDescription::MouseExit,
time,
NULL,
ppt->x,
ppt->y);
::ClientToScreen(AwtToolkit::m_HoldMouse->GetWindowHandle(), ppt);
}
else
// first time in, install the mouse timer
AwtToolkit::CreateTimer();
// update static information
AwtToolkit::m_HoldMouse = this;
//Lock();
// fire java event. Mouse position in client coordinates
::ScreenToClient(m_hWnd, ppt);
AwtToolkit::RaiseJavaEvent(m_pJavaPeer,
AwtEventDescription::MouseEnter,
time,
NULL,
ppt->x,
ppt->y);
//Unlock();
}
return FALSE;
}
BOOL AwtWindow::OnPaint( HDC hdc, int x, int y, int w, int h )
{
//REMIND: Query the component size and return the actual size
PAINTSTRUCT ps;
HDC hDC = ::BeginPaint(m_hWnd, &ps);
// discard (0, 0, 0, 0) rect
if (ps.rcPaint.left || ps.rcPaint.right || ps.rcPaint.top || ps.rcPaint.bottom) {
::FillRect(hDC, &ps.rcPaint, m_BackgroundColor->GetBrush());
AwtToolkit::RaiseJavaEvent(m_pJavaPeer, AwtEventDescription::Expose,
ll_zero_const, NULL,
x, y, w, h);
}
::EndPaint(m_hWnd, &ps);
return TRUE;
}
BOOL AwtWindow::OnDestroy( void )
{
// Release the AwtDC if one was created...
if (m_pAwtDC) {
m_pAwtDC->ResetTargetObject();
m_pAwtDC->Release();
m_pAwtDC = NULL;
}
//
// Restore the previous Window Procedure before the window is destroyed
//
SubclassWindow(FALSE);
//
// check out if this window was holding the mouse
// We want to deal with AwtToolkit::m_HoldMouse only in the gui thread
// so we cut down our chances to dead lock
//
if (AwtToolkit::m_HoldMouse == this) {
// delete timer
AwtToolkit::DestroyTimer();
AwtToolkit::m_HoldMouse = 0;
}
m_hWnd = NULL;
return AwtComponent::OnDestroy();
}