1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 // i72022: ad-hoc to forcibly enable reconversion 28 #if WINVER < 0x0500 29 #undef WINVER 30 #define WINVER 0x0500 31 #endif 32 33 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 34 #include <com/sun/star/container/XIndexAccess.hpp> 35 #include <com/sun/star/beans/XPropertySet.hpp> 36 #include <com/sun/star/awt/Rectangle.hpp> 37 #include <comphelper/processfactory.hxx> 38 #include <unotools/misccfg.hxx> 39 40 #include <string.h> 41 #include <limits.h> 42 43 #include <stdio.h> 44 45 #include <tools/svwin.h> 46 #ifdef __MINGW32__ 47 #include <excpt.h> 48 #endif 49 50 #include <rtl/string.h> 51 #include <rtl/ustring.h> 52 53 #include <osl/module.h> 54 55 #include <tools/debug.hxx> 56 57 #include <vcl/sysdata.hxx> 58 #include <vcl/timer.hxx> 59 #include <vcl/settings.hxx> 60 #include <vcl/keycodes.hxx> 61 #include <vcl/window.hxx> 62 #include <vcl/wrkwin.hxx> 63 #include <vcl/svapp.hxx> 64 #include <vcl/impdel.hxx> 65 66 // Warning in SDK header 67 #if defined(_MSC_VER) && (_MSC_VER > 1400) 68 #pragma warning( disable: 4242 4244 ) 69 #endif 70 #include <win/wincomp.hxx> 71 #include <win/salids.hrc> 72 #include <win/saldata.hxx> 73 #include <win/salinst.h> 74 #include <win/salbmp.h> 75 #include <win/salgdi.h> 76 #include <win/salsys.h> 77 #include <win/salframe.h> 78 #include <win/salvd.h> 79 #include <win/salmenu.h> 80 #include <win/salobj.h> 81 #include <win/saltimer.h> 82 83 #include <impbmp.hxx> 84 #include <window.h> 85 #include <sallayout.hxx> 86 87 #define COMPILE_MULTIMON_STUBS 88 #include <multimon.h> 89 #include <vector> 90 #ifdef __MINGW32__ 91 #include <algorithm> 92 using ::std::max; 93 #endif 94 95 #ifdef WNT 96 #include <oleacc.h> 97 #include <com/sun/star/accessibility/XMSAAService.hpp> 98 #ifndef _WIN32_WCE 99 #define WM_GETOBJECT 0x003D 100 #endif 101 #include <win/g_msaasvc.h> 102 #endif 103 #include <com/sun/star/uno/Exception.hdl> 104 105 #include <time.h> 106 107 using ::rtl::OUString; 108 using namespace ::com::sun::star; 109 using namespace ::com::sun::star::uno; 110 using namespace ::com::sun::star::lang; 111 using namespace ::com::sun::star::container; 112 using namespace ::com::sun::star::beans; 113 114 // The following defines are newly added in Longhorn 115 #ifndef WM_MOUSEHWHEEL 116 # define WM_MOUSEHWHEEL 0x020E 117 #endif 118 #ifndef SPI_GETWHEELSCROLLCHARS 119 # define SPI_GETWHEELSCROLLCHARS 0x006C 120 #endif 121 #ifndef SPI_SETWHEELSCROLLCHARS 122 # define SPI_SETWHEELSCROLLCHARS 0x006D 123 #endif 124 125 126 127 #if OSL_DEBUG_LEVEL > 1 128 void MyOutputDebugString( char *s) { OutputDebugString( s ); } 129 #endif 130 131 // misssing prototypes and constants for LayeredWindows 132 extern "C" { 133 //WINUSERAPI sal_Bool WINAPI SetLayeredWindowAttributes(HWND,COLORREF,BYTE,DWORD); 134 typedef sal_Bool ( WINAPI * SetLayeredWindowAttributes_Proc_T ) (HWND,COLORREF,BYTE,DWORD); 135 static SetLayeredWindowAttributes_Proc_T lpfnSetLayeredWindowAttributes; 136 }; 137 138 // ======================================================================= 139 140 const unsigned int WM_USER_SYSTEM_WINDOW_ACTIVATED = RegisterWindowMessageA("SYSTEM_WINDOW_ACTIVATED"); 141 142 sal_Bool WinSalFrame::mbInReparent = FALSE; 143 144 // ======================================================================= 145 146 // Wegen Fehler in Windows-Headerfiles 147 #ifndef IMN_OPENCANDIDATE 148 #define IMN_OPENCANDIDATE 0x0005 149 #endif 150 #ifndef IMN_CLOSECANDIDATE 151 #define IMN_CLOSECANDIDATE 0x0004 152 #endif 153 154 #ifndef WM_THEMECHANGED 155 #define WM_THEMECHANGED 0x031A 156 #endif 157 158 // Macros for support of WM_UNICHAR & Keyman 6.0 159 #define Uni_UTF32ToSurrogate1(ch) (((unsigned long) (ch) - 0x10000) / 0x400 + 0xD800) 160 #define Uni_UTF32ToSurrogate2(ch) (((unsigned long) (ch) - 0x10000) % 0x400 + 0xDC00) 161 #define Uni_SupplementaryPlanesStart 0x10000 162 163 // ======================================================================= 164 #ifdef WNT 165 using namespace ::com::sun::star::accessibility; 166 XMSAAService* g_acc_manager1 = NULL; 167 #endif 168 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame ); 169 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect = NULL ); 170 171 static void ImplSaveFrameState( WinSalFrame* pFrame ) 172 { 173 // Position, Groesse und Status fuer GetWindowState() merken 174 if ( !pFrame->mbFullScreen ) 175 { 176 sal_Bool bVisible = (GetWindowStyle( pFrame->mhWnd ) & WS_VISIBLE) != 0; 177 if ( IsIconic( pFrame->mhWnd ) ) 178 { 179 pFrame->maState.mnState |= SAL_FRAMESTATE_MINIMIZED; 180 if ( bVisible ) 181 pFrame->mnShowState = SW_SHOWMAXIMIZED; 182 } 183 else if ( IsZoomed( pFrame->mhWnd ) ) 184 { 185 pFrame->maState.mnState &= ~SAL_FRAMESTATE_MINIMIZED; 186 pFrame->maState.mnState |= SAL_FRAMESTATE_MAXIMIZED; 187 if ( bVisible ) 188 pFrame->mnShowState = SW_SHOWMAXIMIZED; 189 pFrame->mbRestoreMaximize = TRUE; 190 191 WINDOWPLACEMENT aPlacement; 192 aPlacement.length = sizeof(aPlacement); 193 if( GetWindowPlacement( pFrame->mhWnd, &aPlacement ) ) 194 { 195 RECT aRect = aPlacement.rcNormalPosition; 196 RECT aRect2 = aRect; 197 AdjustWindowRectEx( &aRect2, GetWindowStyle( pFrame->mhWnd ), 198 FALSE, GetWindowExStyle( pFrame->mhWnd ) ); 199 long nTopDeco = abs( aRect.top - aRect2.top ); 200 long nLeftDeco = abs( aRect.left - aRect2.left ); 201 long nBottomDeco = abs( aRect.bottom - aRect2.bottom ); 202 long nRightDeco = abs( aRect.right - aRect2.right ); 203 204 pFrame->maState.mnX = aRect.left + nLeftDeco; 205 pFrame->maState.mnY = aRect.top + nTopDeco; 206 pFrame->maState.mnWidth = aRect.right - aRect.left - nLeftDeco - nRightDeco; 207 pFrame->maState.mnHeight = aRect.bottom - aRect.top - nTopDeco - nBottomDeco; 208 } 209 } 210 else 211 { 212 RECT aRect; 213 GetWindowRect( pFrame->mhWnd, &aRect ); 214 215 // to be consistent with Unix, the frame state is without(!) decoration 216 RECT aRect2 = aRect; 217 AdjustWindowRectEx( &aRect2, GetWindowStyle( pFrame->mhWnd ), 218 FALSE, GetWindowExStyle( pFrame->mhWnd ) ); 219 long nTopDeco = abs( aRect.top - aRect2.top ); 220 long nLeftDeco = abs( aRect.left - aRect2.left ); 221 long nBottomDeco = abs( aRect.bottom - aRect2.bottom ); 222 long nRightDeco = abs( aRect.right - aRect2.right ); 223 224 pFrame->maState.mnState &= ~(SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED); 225 // subtract decoration 226 pFrame->maState.mnX = aRect.left+nLeftDeco; 227 pFrame->maState.mnY = aRect.top+nTopDeco; 228 pFrame->maState.mnWidth = aRect.right-aRect.left-nLeftDeco-nRightDeco; 229 pFrame->maState.mnHeight = aRect.bottom-aRect.top-nTopDeco-nBottomDeco; 230 if ( bVisible ) 231 pFrame->mnShowState = SW_SHOWNORMAL; 232 pFrame->mbRestoreMaximize = FALSE; 233 } 234 } 235 } 236 237 // ----------------------------------------------------------------------- 238 239 // if pParentRect is set, the workarea of the monitor that contains pParentRect is returned 240 void ImplSalGetWorkArea( HWND hWnd, RECT *pRect, const RECT *pParentRect ) 241 { 242 static int winVerChecked = 0; 243 static int winVerOk = 0; 244 245 // check if we or our parent is fullscreen, then the taskbar should be ignored 246 bool bIgnoreTaskbar = false; 247 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 248 if( pFrame ) 249 { 250 Window *pWin = pFrame->GetWindow(); 251 while( pWin ) 252 { 253 WorkWindow *pWorkWin = (pWin->GetType() == WINDOW_WORKWINDOW) ? (WorkWindow *) pWin : NULL; 254 if( pWorkWin && pWorkWin->ImplGetWindowImpl()->mbReallyVisible && pWorkWin->IsFullScreenMode() ) 255 { 256 bIgnoreTaskbar = true; 257 break; 258 } 259 else 260 pWin = pWin->ImplGetWindowImpl()->mpParent; 261 } 262 } 263 264 if( !winVerChecked ) 265 { 266 winVerChecked = 1; 267 winVerOk = 1; 268 269 // multi monitor calls not available on Win95/NT 270 if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) 271 { 272 if ( aSalShlData.maVersionInfo.dwMajorVersion <= 4 ) 273 winVerOk = 0; // NT 274 } 275 else if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) 276 { 277 if ( aSalShlData.maVersionInfo.dwMajorVersion == 4 && aSalShlData.maVersionInfo.dwMinorVersion == 0 ) 278 winVerOk = 0; // Win95 279 } 280 } 281 282 // calculates the work area taking multiple monitors into account 283 if( winVerOk ) 284 { 285 static int nMonitors = GetSystemMetrics( SM_CMONITORS ); 286 if( nMonitors == 1 ) 287 { 288 if( bIgnoreTaskbar ) 289 { 290 pRect->left = pRect->top = 0; 291 pRect->right = GetSystemMetrics( SM_CXSCREEN ); 292 pRect->bottom = GetSystemMetrics( SM_CYSCREEN ); 293 } 294 else 295 SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 ); 296 } 297 else 298 { 299 if( pParentRect != NULL ) 300 { 301 // return the size of the monitor where pParentRect lives 302 HMONITOR hMonitor; 303 MONITORINFO mi; 304 305 // get the nearest monitor to the passed rect. 306 hMonitor = MonitorFromRect(pParentRect, MONITOR_DEFAULTTONEAREST); 307 308 // get the work area or entire monitor rect. 309 mi.cbSize = sizeof(mi); 310 GetMonitorInfo(hMonitor, &mi); 311 if( !bIgnoreTaskbar ) 312 *pRect = mi.rcWork; 313 else 314 *pRect = mi.rcMonitor; 315 } 316 else 317 { 318 // return the union of all monitors 319 pRect->left = GetSystemMetrics( SM_XVIRTUALSCREEN ); 320 pRect->top = GetSystemMetrics( SM_YVIRTUALSCREEN ); 321 pRect->right = pRect->left + GetSystemMetrics( SM_CXVIRTUALSCREEN ); 322 pRect->bottom = pRect->top + GetSystemMetrics( SM_CYVIRTUALSCREEN ); 323 324 // virtualscreen does not take taskbar into account, so use the corresponding 325 // diffs between screen and workarea from the default screen 326 // however, this is still not perfect: the taskbar might not be on the primary screen 327 if( !bIgnoreTaskbar ) 328 { 329 RECT wRect, scrRect; 330 SystemParametersInfo( SPI_GETWORKAREA, 0, &wRect, 0 ); 331 scrRect.left = 0; 332 scrRect.top = 0; 333 scrRect.right = GetSystemMetrics( SM_CXSCREEN ); 334 scrRect.bottom = GetSystemMetrics( SM_CYSCREEN ); 335 336 pRect->left += wRect.left; 337 pRect->top += wRect.top; 338 pRect->right -= scrRect.right - wRect.right; 339 pRect->bottom -= scrRect.bottom - wRect.bottom; 340 } 341 } 342 } 343 } 344 else 345 { 346 if( bIgnoreTaskbar ) 347 { 348 pRect->left = pRect->top = 0; 349 pRect->right = GetSystemMetrics( SM_CXSCREEN ); 350 pRect->bottom = GetSystemMetrics( SM_CYSCREEN ); 351 } 352 else 353 SystemParametersInfo( SPI_GETWORKAREA, 0, pRect, 0 ); 354 } 355 } 356 357 // ======================================================================= 358 359 SalFrame* ImplSalCreateFrame( WinSalInstance* pInst, 360 HWND hWndParent, sal_uLong nSalFrameStyle ) 361 { 362 WinSalFrame* pFrame = new WinSalFrame; 363 HWND hWnd; 364 DWORD nSysStyle = 0; 365 DWORD nExSysStyle = 0; 366 sal_Bool bSubFrame = FALSE; 367 368 if( getenv( "SAL_SYNCHRONIZE" ) ) // no buffering of drawing commands 369 GdiSetBatchLimit( 1 ); 370 371 static int bLayeredAPI = -1; 372 if( bLayeredAPI == -1 ) 373 { 374 bLayeredAPI = 0; 375 // check for W2k and XP 376 if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 ) 377 { 378 oslModule pLib = osl_loadAsciiModule( "user32", SAL_LOADMODULE_DEFAULT ); 379 oslGenericFunction pFunc = NULL; 380 if( pLib ) 381 pFunc = osl_getAsciiFunctionSymbol( pLib, "SetLayeredWindowAttributes" ); 382 383 lpfnSetLayeredWindowAttributes = ( SetLayeredWindowAttributes_Proc_T ) pFunc; 384 385 bLayeredAPI = pFunc ? 1 : 0; 386 } 387 } 388 static const char* pEnvTransparentFloats = getenv("SAL_TRANSPARENT_FLOATS" ); 389 390 // determine creation data 391 if ( nSalFrameStyle & (SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_SYSTEMCHILD) ) 392 { 393 nSysStyle |= WS_CHILD; 394 if( nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD ) 395 nSysStyle |= WS_CLIPSIBLINGS; 396 } 397 else 398 { 399 // #i87402# commenting out WS_CLIPCHILDREN 400 // this breaks SAL_FRAME_STYLE_SYSTEMCHILD handling, which is not 401 // used currently. Probably SAL_FRAME_STYLE_SYSTEMCHILD should be 402 // removed again. 403 404 // nSysStyle |= WS_CLIPCHILDREN; 405 if ( hWndParent ) 406 { 407 nSysStyle |= WS_POPUP; 408 bSubFrame = TRUE; 409 pFrame->mbNoIcon = TRUE; 410 } 411 else 412 { 413 // Only with WS_OVERLAPPED we get a useful default position/size 414 if ( (nSalFrameStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE)) == 415 (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_MOVEABLE) ) 416 nSysStyle |= WS_OVERLAPPED; 417 else 418 { 419 nSysStyle |= WS_POPUP; 420 if ( !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) ) 421 nExSysStyle |= WS_EX_TOOLWINDOW; // avoid taskbar appearance, for e.g. splash screen 422 } 423 } 424 425 if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE ) 426 { 427 pFrame->mbCaption = TRUE; 428 nSysStyle |= WS_SYSMENU | WS_CAPTION; 429 if ( !hWndParent ) 430 nSysStyle |= WS_SYSMENU | WS_MINIMIZEBOX; 431 else 432 nExSysStyle |= WS_EX_DLGMODALFRAME; 433 434 if ( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE ) 435 { 436 pFrame->mbSizeBorder = TRUE; 437 nSysStyle |= WS_THICKFRAME; 438 if ( !hWndParent ) 439 nSysStyle |= WS_MAXIMIZEBOX; 440 } 441 else 442 pFrame->mbFixBorder = TRUE; 443 444 if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT ) 445 nExSysStyle |= WS_EX_APPWINDOW; 446 } 447 if( nSalFrameStyle & SAL_FRAME_STYLE_TOOLWINDOW 448 // #100656# toolwindows lead to bad alt-tab behavior, if they have the focus 449 // you must press it twice to leave the application 450 // so toolwindows are only used for non sizeable windows 451 // which are typically small, so a small caption makes sense 452 453 // #103578# looked too bad - above changes reverted 454 /* && !(nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE) */ ) 455 { 456 pFrame->mbNoIcon = TRUE; 457 nExSysStyle |= WS_EX_TOOLWINDOW; 458 if ( pEnvTransparentFloats && bLayeredAPI == 1 /*&& !(nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE) */) 459 nExSysStyle |= WS_EX_LAYERED; 460 } 461 } 462 if ( nSalFrameStyle & SAL_FRAME_STYLE_FLOAT ) 463 { 464 nExSysStyle |= WS_EX_TOOLWINDOW; 465 pFrame->mbFloatWin = TRUE; 466 467 if ( (bLayeredAPI == 1) && (pEnvTransparentFloats /* does not work remote! || (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) */ ) ) 468 nExSysStyle |= WS_EX_LAYERED; 469 470 } 471 if( (nSalFrameStyle & SAL_FRAME_STYLE_TOOLTIP) || (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) ) 472 nExSysStyle |= WS_EX_TOPMOST; 473 474 // init frame data 475 pFrame->mnStyle = nSalFrameStyle; 476 477 // determine show style 478 pFrame->mnShowState = SW_SHOWNORMAL; 479 if ( (nSysStyle & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME) ) 480 { 481 if ( GetSystemMetrics( SM_CXSCREEN ) <= 1024 ) 482 pFrame->mnShowState = SW_SHOWMAXIMIZED; 483 else 484 { 485 if ( nSalFrameStyle & SAL_FRAME_STYLE_DEFAULT ) 486 { 487 SalData* pSalData = GetSalData(); 488 pFrame->mnShowState = pSalData->mnCmdShow; 489 if ( (pFrame->mnShowState != SW_SHOWMINIMIZED) && 490 (pFrame->mnShowState != SW_MINIMIZE) && 491 (pFrame->mnShowState != SW_SHOWMINNOACTIVE) ) 492 { 493 if ( (pFrame->mnShowState == SW_SHOWMAXIMIZED) || 494 (pFrame->mnShowState == SW_MAXIMIZE) ) 495 pFrame->mbOverwriteState = FALSE; 496 pFrame->mnShowState = SW_SHOWMAXIMIZED; 497 } 498 else 499 pFrame->mbOverwriteState = FALSE; 500 } 501 else 502 { 503 // Document Windows are also maximized, if the current Document Window 504 // is also maximized 505 HWND hWnd = GetForegroundWindow(); 506 if ( hWnd && IsMaximized( hWnd ) && 507 (GetWindowInstance( hWnd ) == pInst->mhInst) && 508 ((GetWindowStyle( hWnd ) & (WS_POPUP | WS_MAXIMIZEBOX | WS_THICKFRAME)) == (WS_MAXIMIZEBOX | WS_THICKFRAME)) ) 509 pFrame->mnShowState = SW_SHOWMAXIMIZED; 510 } 511 } 512 } 513 514 // create frame 515 if( true/*aSalShlData.mbWNT*/ ) 516 { 517 LPCWSTR pClassName; 518 if ( bSubFrame ) 519 { 520 if ( nSalFrameStyle & (SAL_FRAME_STYLE_MOVEABLE|SAL_FRAME_STYLE_NOSHADOW) ) // check if shadow not wanted 521 pClassName = SAL_SUBFRAME_CLASSNAMEW; 522 else 523 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW; // undecorated floaters will get shadow on XP 524 } 525 else 526 { 527 if ( nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE ) 528 pClassName = SAL_FRAME_CLASSNAMEW; 529 else 530 pClassName = SAL_TMPSUBFRAME_CLASSNAMEW; 531 } 532 hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle, 533 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 534 hWndParent, 0, pInst->mhInst, (void*)pFrame ); 535 if( !hWnd ) 536 ImplWriteLastError( GetLastError(), "CreateWindowEx" ); 537 #if OSL_DEBUG_LEVEL > 1 538 // set transparency value 539 if( bLayeredAPI == 1 && GetWindowExStyle( hWnd ) & WS_EX_LAYERED ) 540 lpfnSetLayeredWindowAttributes( hWnd, 0, 230, 0x00000002 /*LWA_ALPHA*/ ); 541 #endif 542 } 543 if ( !hWnd ) 544 { 545 delete pFrame; 546 return NULL; 547 } 548 549 // If we have an Window with an Caption Bar and without 550 // an MaximizeBox, we change the SystemMenu 551 if ( (nSysStyle & (WS_CAPTION | WS_MAXIMIZEBOX)) == (WS_CAPTION) ) 552 { 553 HMENU hSysMenu = GetSystemMenu( hWnd, FALSE ); 554 if ( hSysMenu ) 555 { 556 if ( !(nSysStyle & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX)) ) 557 DeleteMenu( hSysMenu, SC_RESTORE, MF_BYCOMMAND ); 558 else 559 EnableMenuItem( hSysMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED ); 560 if ( !(nSysStyle & WS_MINIMIZEBOX) ) 561 DeleteMenu( hSysMenu, SC_MINIMIZE, MF_BYCOMMAND ); 562 if ( !(nSysStyle & WS_MAXIMIZEBOX) ) 563 DeleteMenu( hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND ); 564 if ( !(nSysStyle & WS_THICKFRAME) ) 565 DeleteMenu( hSysMenu, SC_SIZE, MF_BYCOMMAND ); 566 } 567 } 568 if ( (nSysStyle & WS_SYSMENU) && !(nSalFrameStyle & SAL_FRAME_STYLE_CLOSEABLE) ) 569 { 570 HMENU hSysMenu = GetSystemMenu( hWnd, FALSE ); 571 if ( hSysMenu ) 572 EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED | MF_DISABLED ); 573 } 574 575 // reset input context 576 pFrame->mhDefIMEContext = ImmAssociateContext( hWnd, 0 ); 577 578 // determine output size and state 579 RECT aRect; 580 GetClientRect( hWnd, &aRect ); 581 pFrame->mnWidth = aRect.right; 582 pFrame->mnHeight = aRect.bottom; 583 ImplSaveFrameState( pFrame ); 584 pFrame->mbDefPos = TRUE; 585 586 UpdateFrameGeometry( hWnd, pFrame ); 587 588 if( pFrame->mnShowState == SW_SHOWMAXIMIZED ) 589 { 590 // #96084 set a useful internal window size because 591 // the window will not be maximized (and the size updated) before show() 592 593 SetMaximizedFrameGeometry( hWnd, pFrame ); 594 } 595 596 return pFrame; 597 } 598 599 // helper that only creates the HWND 600 // to allow for easy reparenting of system windows, (i.e. destroy and create new) 601 HWND ImplSalReCreateHWND( HWND hWndParent, HWND oldhWnd, sal_Bool bAsChild ) 602 { 603 HINSTANCE hInstance = GetSalData()->mhInst; 604 ULONG nSysStyle = GetWindowLong( oldhWnd, GWL_STYLE ); 605 ULONG nExSysStyle = GetWindowLong( oldhWnd, GWL_EXSTYLE ); 606 607 if( bAsChild ) 608 { 609 nSysStyle = WS_CHILD; 610 nExSysStyle = 0; 611 } 612 613 LPCWSTR pClassName = SAL_SUBFRAME_CLASSNAMEW; 614 HWND hWnd = CreateWindowExW( nExSysStyle, pClassName, L"", nSysStyle, 615 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 616 hWndParent, 0, hInstance, (void*)GetWindowPtr( oldhWnd ) ); 617 return hWnd; 618 } 619 620 // ======================================================================= 621 622 // Uebersetzungstabelle von System-Keycodes in StarView-Keycodes 623 #define KEY_TAB_SIZE 146 624 625 static sal_uInt16 aImplTranslateKeyTab[KEY_TAB_SIZE] = 626 { 627 // StarView-Code System-Code Index 628 0, // 0 629 0, // VK_LBUTTON 1 630 0, // VK_RBUTTON 2 631 0, // VK_CANCEL 3 632 0, // VK_MBUTTON 4 633 0, // 5 634 0, // 6 635 0, // 7 636 KEY_BACKSPACE, // VK_BACK 8 637 KEY_TAB, // VK_TAB 9 638 0, // 10 639 0, // 11 640 0, // VK_CLEAR 12 641 KEY_RETURN, // VK_RETURN 13 642 0, // 14 643 0, // 15 644 0, // VK_SHIFT 16 645 0, // VK_CONTROL 17 646 0, // VK_MENU 18 647 0, // VK_PAUSE 19 648 0, // VK_CAPITAL 20 649 0, // VK_HANGUL 21 650 0, // 22 651 0, // 23 652 0, // 24 653 KEY_HANGUL_HANJA, // VK_HANJA 25 654 0, // 26 655 KEY_ESCAPE, // VK_ESCAPE 27 656 0, // 28 657 0, // 29 658 0, // 30 659 0, // 31 660 KEY_SPACE, // VK_SPACE 32 661 KEY_PAGEUP, // VK_PRIOR 33 662 KEY_PAGEDOWN, // VK_NEXT 34 663 KEY_END, // VK_END 35 664 KEY_HOME, // VK_HOME 36 665 KEY_LEFT, // VK_LEFT 37 666 KEY_UP, // VK_UP 38 667 KEY_RIGHT, // VK_RIGHT 39 668 KEY_DOWN, // VK_DOWN 40 669 0, // VK_SELECT 41 670 0, // VK_PRINT 42 671 0, // VK_EXECUTE 43 672 0, // VK_SNAPSHOT 44 673 KEY_INSERT, // VK_INSERT 45 674 KEY_DELETE, // VK_DELETE 46 675 KEY_HELP, // VK_HELP 47 676 KEY_0, // 48 677 KEY_1, // 49 678 KEY_2, // 50 679 KEY_3, // 51 680 KEY_4, // 52 681 KEY_5, // 53 682 KEY_6, // 54 683 KEY_7, // 55 684 KEY_8, // 56 685 KEY_9, // 57 686 0, // 58 687 0, // 59 688 0, // 60 689 0, // 61 690 0, // 62 691 0, // 63 692 0, // 64 693 KEY_A, // 65 694 KEY_B, // 66 695 KEY_C, // 67 696 KEY_D, // 68 697 KEY_E, // 69 698 KEY_F, // 70 699 KEY_G, // 71 700 KEY_H, // 72 701 KEY_I, // 73 702 KEY_J, // 74 703 KEY_K, // 75 704 KEY_L, // 76 705 KEY_M, // 77 706 KEY_N, // 78 707 KEY_O, // 79 708 KEY_P, // 80 709 KEY_Q, // 81 710 KEY_R, // 82 711 KEY_S, // 83 712 KEY_T, // 84 713 KEY_U, // 85 714 KEY_V, // 86 715 KEY_W, // 87 716 KEY_X, // 88 717 KEY_Y, // 89 718 KEY_Z, // 90 719 0, // VK_LWIN 91 720 0, // VK_RWIN 92 721 KEY_CONTEXTMENU, // VK_APPS 93 722 0, // 94 723 0, // 95 724 KEY_0, // VK_NUMPAD0 96 725 KEY_1, // VK_NUMPAD1 97 726 KEY_2, // VK_NUMPAD2 98 727 KEY_3, // VK_NUMPAD3 99 728 KEY_4, // VK_NUMPAD4 100 729 KEY_5, // VK_NUMPAD5 101 730 KEY_6, // VK_NUMPAD6 102 731 KEY_7, // VK_NUMPAD7 103 732 KEY_8, // VK_NUMPAD8 104 733 KEY_9, // VK_NUMPAD9 105 734 KEY_MULTIPLY, // VK_MULTIPLY 106 735 KEY_ADD, // VK_ADD 107 736 KEY_DECIMAL, // VK_SEPARATOR 108 737 KEY_SUBTRACT, // VK_SUBTRACT 109 738 KEY_DECIMAL, // VK_DECIMAL 110 739 KEY_DIVIDE, // VK_DIVIDE 111 740 KEY_F1, // VK_F1 112 741 KEY_F2, // VK_F2 113 742 KEY_F3, // VK_F3 114 743 KEY_F4, // VK_F4 115 744 KEY_F5, // VK_F5 116 745 KEY_F6, // VK_F6 117 746 KEY_F7, // VK_F7 118 747 KEY_F8, // VK_F8 119 748 KEY_F9, // VK_F9 120 749 KEY_F10, // VK_F10 121 750 KEY_F11, // VK_F11 122 751 KEY_F12, // VK_F12 123 752 KEY_F13, // VK_F13 124 753 KEY_F14, // VK_F14 125 754 KEY_F15, // VK_F15 126 755 KEY_F16, // VK_F16 127 756 KEY_F17, // VK_F17 128 757 KEY_F18, // VK_F18 129 758 KEY_F19, // VK_F19 130 759 KEY_F20, // VK_F20 131 760 KEY_F21, // VK_F21 132 761 KEY_F22, // VK_F22 133 762 KEY_F23, // VK_F23 134 763 KEY_F24, // VK_F24 135 764 0, // 136 765 0, // 137 766 0, // 138 767 0, // 139 768 0, // 140 769 0, // 141 770 0, // 142 771 0, // 143 772 0, // NUMLOCK 144 773 0 // SCROLLLOCK 145 774 }; 775 776 // ======================================================================= 777 778 static UINT ImplSalGetWheelScrollLines() 779 { 780 UINT nScrLines = 0; 781 HWND hWndMsWheel = WIN_FindWindow( MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE ); 782 if ( hWndMsWheel ) 783 { 784 UINT nGetScrollLinesMsgId = RegisterWindowMessage( MSH_SCROLL_LINES ); 785 nScrLines = (UINT)ImplSendMessage( hWndMsWheel, nGetScrollLinesMsgId, 0, 0 ); 786 } 787 788 if ( !nScrLines ) 789 if( !SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &nScrLines, 0 ) ) 790 nScrLines = 0 ; 791 792 if ( !nScrLines ) 793 nScrLines = 3; 794 795 return nScrLines; 796 } 797 798 // ----------------------------------------------------------------------- 799 800 static UINT ImplSalGetWheelScrollChars() 801 { 802 UINT nScrChars = 0; 803 if( !SystemParametersInfo( SPI_GETWHEELSCROLLCHARS, 0, &nScrChars, 0 ) ) 804 { 805 // Depending on Windows version, use proper default or 1 (when 806 // driver emulates hscroll) 807 if( VER_PLATFORM_WIN32_NT == aSalShlData.maVersionInfo.dwPlatformId && 808 aSalShlData.maVersionInfo.dwMajorVersion < 6 ) 809 { 810 // Windows 2000 & WinXP : emulating driver, use step size 811 // of 1 812 return 1; 813 } 814 else 815 { 816 // Longhorn or above: use proper default value of 3 817 return 3; 818 } 819 } 820 821 // system settings successfully read 822 return nScrChars; 823 } 824 825 // ----------------------------------------------------------------------- 826 827 static void ImplSalAddBorder( const WinSalFrame* pFrame, int& width, int& height ) 828 { 829 // transform client size into window size 830 RECT aWinRect; 831 aWinRect.left = 0; 832 aWinRect.right = width-1; 833 aWinRect.top = 0; 834 aWinRect.bottom = height-1; 835 AdjustWindowRectEx( &aWinRect, GetWindowStyle( pFrame->mhWnd ), 836 FALSE, GetWindowExStyle( pFrame->mhWnd ) ); 837 width = aWinRect.right - aWinRect.left + 1; 838 height = aWinRect.bottom - aWinRect.top + 1; 839 } 840 841 // ----------------------------------------------------------------------- 842 843 static void ImplSalCalcFullScreenSize( const WinSalFrame* pFrame, 844 int& rX, int& rY, int& rDX, int& rDY ) 845 { 846 // set window to screen size 847 int nFrameX; 848 int nFrameY; 849 int nCaptionY; 850 int nScreenX = 0; 851 int nScreenY = 0; 852 int nScreenDX = 0; 853 int nScreenDY = 0; 854 855 if ( pFrame->mbSizeBorder ) 856 { 857 nFrameX = GetSystemMetrics( SM_CXSIZEFRAME ); 858 nFrameY = GetSystemMetrics( SM_CYSIZEFRAME ); 859 } 860 else if ( pFrame->mbFixBorder ) 861 { 862 nFrameX = GetSystemMetrics( SM_CXFIXEDFRAME ); 863 nFrameY = GetSystemMetrics( SM_CYFIXEDFRAME ); 864 } 865 else if ( pFrame->mbBorder ) 866 { 867 nFrameX = GetSystemMetrics( SM_CXBORDER ); 868 nFrameY = GetSystemMetrics( SM_CYBORDER ); 869 } 870 else 871 { 872 nFrameX = 0; 873 nFrameY = 0; 874 } 875 if ( pFrame->mbCaption ) 876 nCaptionY = GetSystemMetrics( SM_CYCAPTION ); 877 else 878 nCaptionY = 0; 879 880 try 881 { 882 uno::Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW ); 883 uno::Reference< XIndexAccess > xMultiMon( xFactory->createInstance(OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.DisplayAccess" ) ) ), UNO_QUERY_THROW ); 884 sal_Int32 nMonitors = xMultiMon->getCount(); 885 if( (pFrame->mnDisplay >= 0) && (pFrame->mnDisplay < nMonitors) ) 886 { 887 uno::Reference< XPropertySet > xMonitor( xMultiMon->getByIndex( pFrame->mnDisplay ), UNO_QUERY_THROW ); 888 com::sun::star::awt::Rectangle aRect; 889 if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect ) 890 { 891 nScreenX = aRect.X; 892 nScreenY = aRect.Y; 893 nScreenDX = aRect.Width+1; // difference between java/awt convention and vcl 894 nScreenDY = aRect.Height+1; // difference between java/awt convention and vcl 895 } 896 } 897 else 898 { 899 Rectangle aCombined; 900 uno::Reference< XPropertySet > xMonitor( xMultiMon->getByIndex( 0 ), UNO_QUERY_THROW ); 901 com::sun::star::awt::Rectangle aRect; 902 if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect ) 903 { 904 aCombined.Left() = aRect.X; 905 aCombined.Top() = aRect.Y; 906 aCombined.Right() = aRect.X + aRect.Width; 907 aCombined.Bottom() = aRect.Y + aRect.Height; 908 for( sal_Int32 i = 1 ; i < nMonitors ; i++ ) 909 { 910 xMonitor = uno::Reference< XPropertySet >( xMultiMon->getByIndex(i), UNO_QUERY_THROW ); 911 if( xMonitor->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "ScreenArea" ) ) ) >>= aRect ) 912 { 913 aCombined.Union( Rectangle( aRect.X, aRect.Y, aRect.X+aRect.Width, aRect.Y+aRect.Height ) ); 914 } 915 } 916 } 917 nScreenX = aCombined.Left(); 918 nScreenY = aCombined.Top(); 919 nScreenDX = aCombined.GetWidth(); 920 nScreenDY = aCombined.GetHeight(); 921 } 922 } 923 catch( Exception& ) 924 { 925 } 926 927 if( !nScreenDX || !nScreenDY ) 928 { 929 nScreenDX = GetSystemMetrics( SM_CXSCREEN ); 930 nScreenDY = GetSystemMetrics( SM_CYSCREEN ); 931 } 932 933 rX = nScreenX -nFrameX; 934 rY = nScreenY -(nFrameY+nCaptionY); 935 rDX = nScreenDX+(nFrameX*2); 936 rDY = nScreenDY+(nFrameY*2)+nCaptionY; 937 } 938 939 // ----------------------------------------------------------------------- 940 941 static void ImplSalFrameFullScreenPos( WinSalFrame* pFrame, sal_Bool bAlways = FALSE ) 942 { 943 if ( bAlways || !IsIconic( pFrame->mhWnd ) ) 944 { 945 // set window to screen size 946 int nX; 947 int nY; 948 int nWidth; 949 int nHeight; 950 ImplSalCalcFullScreenSize( pFrame, nX, nY, nWidth, nHeight ); 951 SetWindowPos( pFrame->mhWnd, 0, 952 nX, nY, nWidth, nHeight, 953 SWP_NOZORDER | SWP_NOACTIVATE ); 954 } 955 } 956 957 // ----------------------------------------------------------------------- 958 959 WinSalFrame::WinSalFrame() 960 { 961 SalData* pSalData = GetSalData(); 962 963 mhWnd = 0; 964 mhCursor = LoadCursor( 0, IDC_ARROW ); 965 mhDefIMEContext = 0; 966 mpGraphics = NULL; 967 mpGraphics2 = NULL; 968 mnShowState = SW_SHOWNORMAL; 969 mnWidth = 0; 970 mnHeight = 0; 971 mnMinWidth = 0; 972 mnMinHeight = 0; 973 mnMaxWidth = SHRT_MAX; 974 mnMaxHeight = SHRT_MAX; 975 mnInputLang = 0; 976 mnInputCodePage = 0; 977 mbGraphics = FALSE; 978 mbCaption = FALSE; 979 mbBorder = FALSE; 980 mbFixBorder = FALSE; 981 mbSizeBorder = FALSE; 982 mbFullScreen = FALSE; 983 mbPresentation = FALSE; 984 mbInShow = FALSE; 985 mbRestoreMaximize = FALSE; 986 mbInMoveMsg = FALSE; 987 mbInSizeMsg = FALSE; 988 mbFullScreenToolWin = FALSE; 989 mbDefPos = TRUE; 990 mbOverwriteState = TRUE; 991 mbIME = FALSE; 992 mbHandleIME = FALSE; 993 mbSpezIME = FALSE; 994 mbAtCursorIME = FALSE; 995 mbCandidateMode = FALSE; 996 mbFloatWin = FALSE; 997 mbNoIcon = FALSE; 998 mSelectedhMenu = 0; 999 mLastActivatedhMenu = 0; 1000 mpClipRgnData = NULL; 1001 mbFirstClipRect = TRUE; 1002 mpNextClipRect = NULL; 1003 mnDisplay = 0; 1004 1005 memset( &maState, 0, sizeof( SalFrameState ) ); 1006 maSysData.nSize = sizeof( SystemEnvData ); 1007 1008 memset( &maGeometry, 0, sizeof( maGeometry ) ); 1009 1010 // Daten ermitteln, wenn erster Frame angelegt wird 1011 if ( !pSalData->mpFirstFrame ) 1012 { 1013 if ( !aSalShlData.mnWheelMsgId ) 1014 aSalShlData.mnWheelMsgId = RegisterWindowMessage( MSH_MOUSEWHEEL ); 1015 if ( !aSalShlData.mnWheelScrollLines ) 1016 aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines(); 1017 if ( !aSalShlData.mnWheelScrollChars ) 1018 aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars(); 1019 } 1020 1021 // insert frame in framelist 1022 mpNextFrame = pSalData->mpFirstFrame; 1023 pSalData->mpFirstFrame = this; 1024 } 1025 1026 // ----------------------------------------------------------------------- 1027 void WinSalFrame::updateScreenNumber() 1028 { 1029 if( mnDisplay == -1 ) // spans all monitors 1030 return; 1031 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem()); 1032 if( pSys ) 1033 { 1034 const std::vector<WinSalSystem::DisplayMonitor>& rMonitors = 1035 pSys->getMonitors(); 1036 Point aPoint( maGeometry.nX, maGeometry.nY ); 1037 size_t nMon = rMonitors.size(); 1038 for( size_t i = 0; i < nMon; i++ ) 1039 { 1040 if( rMonitors[i].m_aArea.IsInside( aPoint ) ) 1041 { 1042 mnDisplay = static_cast<sal_Int32>(i); 1043 maGeometry.nScreenNumber = static_cast<unsigned int>(i); 1044 } 1045 } 1046 } 1047 } 1048 1049 // ----------------------------------------------------------------------- 1050 1051 WinSalFrame::~WinSalFrame() 1052 { 1053 SalData* pSalData = GetSalData(); 1054 1055 if( mpClipRgnData ) 1056 delete [] (BYTE*)mpClipRgnData; 1057 1058 // remove frame from framelist 1059 WinSalFrame** ppFrame = &pSalData->mpFirstFrame; 1060 for(; (*ppFrame != this) && *ppFrame; ppFrame = &(*ppFrame)->mpNextFrame ); 1061 if( *ppFrame ) 1062 *ppFrame = mpNextFrame; 1063 mpNextFrame = NULL; 1064 1065 // Release Cache DC 1066 if ( mpGraphics2 && 1067 mpGraphics2->getHDC() ) 1068 ReleaseGraphics( mpGraphics2 ); 1069 1070 // destroy saved DC 1071 if ( mpGraphics ) 1072 { 1073 if ( mpGraphics->mhDefPal ) 1074 SelectPalette( mpGraphics->getHDC(), mpGraphics->mhDefPal, TRUE ); 1075 ImplSalDeInitGraphics( mpGraphics ); 1076 ReleaseDC( mhWnd, mpGraphics->getHDC() ); 1077 delete mpGraphics; 1078 mpGraphics = NULL; 1079 } 1080 1081 if ( mhWnd ) 1082 { 1083 // reset mouse leave data 1084 if ( pSalData->mhWantLeaveMsg == mhWnd ) 1085 { 1086 pSalData->mhWantLeaveMsg = 0; 1087 if ( pSalData->mpMouseLeaveTimer ) 1088 { 1089 delete pSalData->mpMouseLeaveTimer; 1090 pSalData->mpMouseLeaveTimer = NULL; 1091 } 1092 } 1093 1094 // destroy system frame 1095 if ( !DestroyWindow( mhWnd ) ) 1096 SetWindowPtr( mhWnd, 0 ); 1097 1098 mhWnd = 0; 1099 } 1100 } 1101 1102 // ----------------------------------------------------------------------- 1103 1104 SalGraphics* WinSalFrame::GetGraphics() 1105 { 1106 if ( mbGraphics ) 1107 return NULL; 1108 1109 // Other threads get an own DC, because Windows modify in the 1110 // other case our DC (changing clip region), when they send a 1111 // WM_ERASEBACKGROUND message 1112 SalData* pSalData = GetSalData(); 1113 if ( pSalData->mnAppThreadId != GetCurrentThreadId() ) 1114 { 1115 // We use only three CacheDC's for all threads, because W9x is limited 1116 // to max. 5 Cache DC's per thread 1117 if ( pSalData->mnCacheDCInUse >= 3 ) 1118 return NULL; 1119 1120 if ( !mpGraphics2 ) 1121 { 1122 mpGraphics2 = new WinSalGraphics; 1123 mpGraphics2->setHDC(0); 1124 mpGraphics2->mhWnd = mhWnd; 1125 mpGraphics2->mbPrinter = FALSE; 1126 mpGraphics2->mbVirDev = FALSE; 1127 mpGraphics2->mbWindow = TRUE; 1128 mpGraphics2->mbScreen = TRUE; 1129 } 1130 1131 HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, 1132 SAL_MSG_GETDC, 1133 (WPARAM)mhWnd, 0 ); 1134 if ( hDC ) 1135 { 1136 mpGraphics2->setHDC(hDC); 1137 if ( pSalData->mhDitherPal ) 1138 { 1139 mpGraphics2->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); 1140 RealizePalette( hDC ); 1141 } 1142 ImplSalInitGraphics( mpGraphics2 ); 1143 mbGraphics = TRUE; 1144 1145 pSalData->mnCacheDCInUse++; 1146 return mpGraphics2; 1147 } 1148 else 1149 return NULL; 1150 } 1151 else 1152 { 1153 if ( !mpGraphics ) 1154 { 1155 HDC hDC = GetDC( mhWnd ); 1156 if ( hDC ) 1157 { 1158 mpGraphics = new WinSalGraphics; 1159 mpGraphics->setHDC(hDC); 1160 mpGraphics->mhWnd = mhWnd; 1161 mpGraphics->mbPrinter = FALSE; 1162 mpGraphics->mbVirDev = FALSE; 1163 mpGraphics->mbWindow = TRUE; 1164 mpGraphics->mbScreen = TRUE; 1165 if ( pSalData->mhDitherPal ) 1166 { 1167 mpGraphics->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); 1168 RealizePalette( hDC ); 1169 } 1170 ImplSalInitGraphics( mpGraphics ); 1171 mbGraphics = TRUE; 1172 } 1173 } 1174 else 1175 mbGraphics = TRUE; 1176 1177 return mpGraphics; 1178 } 1179 } 1180 1181 // ----------------------------------------------------------------------- 1182 1183 void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics ) 1184 { 1185 if ( mpGraphics2 == pGraphics ) 1186 { 1187 if ( mpGraphics2->getHDC() ) 1188 { 1189 SalData* pSalData = GetSalData(); 1190 if ( mpGraphics2->mhDefPal ) 1191 SelectPalette( mpGraphics2->getHDC(), mpGraphics2->mhDefPal, TRUE ); 1192 ImplSalDeInitGraphics( mpGraphics2 ); 1193 ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, 1194 SAL_MSG_RELEASEDC, 1195 (WPARAM)mhWnd, 1196 (LPARAM)mpGraphics2->getHDC() ); 1197 mpGraphics2->setHDC(0); 1198 pSalData->mnCacheDCInUse--; 1199 } 1200 } 1201 1202 mbGraphics = FALSE; 1203 } 1204 1205 // ----------------------------------------------------------------------- 1206 1207 sal_Bool WinSalFrame::PostEvent( void* pData ) 1208 { 1209 return (sal_Bool)ImplPostMessage( mhWnd, SAL_MSG_USEREVENT, 0, (LPARAM)pData ); 1210 } 1211 1212 // ----------------------------------------------------------------------- 1213 1214 void WinSalFrame::SetTitle( const XubString& rTitle ) 1215 { 1216 DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::SetTitle(): WCHAR != sal_Unicode" ); 1217 1218 if ( !SetWindowTextW( mhWnd, reinterpret_cast<LPCWSTR>(rTitle.GetBuffer()) ) ) 1219 { 1220 ByteString aAnsiTitle = ImplSalGetWinAnsiString( rTitle ); 1221 SetWindowTextA( mhWnd, aAnsiTitle.GetBuffer() ); 1222 } 1223 } 1224 1225 // ----------------------------------------------------------------------- 1226 1227 void WinSalFrame::SetIcon( sal_uInt16 nIcon ) 1228 { 1229 // If we have a window without an Icon (for example a dialog), ignore this call 1230 if ( mbNoIcon ) 1231 return; 1232 1233 // 0 means default (class) icon 1234 HICON hIcon = NULL, hSmIcon = NULL; 1235 if ( !nIcon ) 1236 nIcon = 1; 1237 1238 ImplLoadSalIcon( nIcon, hIcon, hSmIcon ); 1239 1240 DBG_ASSERT( hIcon , "WinSalFrame::SetIcon(): Could not load large icon !" ); 1241 DBG_ASSERT( hSmIcon , "WinSalFrame::SetIcon(): Could not load small icon !" ); 1242 1243 ImplSendMessage( mhWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon ); 1244 ImplSendMessage( mhWnd, WM_SETICON, ICON_SMALL, (LPARAM)hSmIcon ); 1245 } 1246 1247 // ----------------------------------------------------------------------- 1248 1249 void WinSalFrame::SetMenu( SalMenu* pSalMenu ) 1250 { 1251 WinSalMenu* pWMenu = static_cast<WinSalMenu*>(pSalMenu); 1252 if( pSalMenu && pWMenu->mbMenuBar ) 1253 ::SetMenu( mhWnd, pWMenu->mhMenu ); 1254 } 1255 1256 void WinSalFrame::DrawMenuBar() 1257 { 1258 ::DrawMenuBar( mhWnd ); 1259 } 1260 1261 // ----------------------------------------------------------------------- 1262 HWND ImplGetParentHwnd( HWND hWnd ) 1263 { 1264 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 1265 if( !pFrame || !pFrame->GetWindow()) 1266 return ::GetParent( hWnd ); 1267 Window *pRealParent = pFrame->GetWindow()->ImplGetWindowImpl()->mpRealParent; 1268 if( pRealParent ) 1269 return static_cast<WinSalFrame*>(pRealParent->ImplGetWindowImpl()->mpFrame)->mhWnd; 1270 else 1271 return ::GetParent( hWnd ); 1272 1273 } 1274 1275 // ----------------------------------------------------------------------- 1276 1277 SalFrame* WinSalFrame::GetParent() const 1278 { 1279 return GetWindowPtr( ImplGetParentHwnd( mhWnd ) ); 1280 } 1281 1282 // ----------------------------------------------------------------------- 1283 1284 static void ImplSalShow( HWND hWnd, sal_Bool bVisible, sal_Bool bNoActivate ) 1285 { 1286 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 1287 if ( !pFrame ) 1288 return; 1289 1290 if ( bVisible ) 1291 { 1292 pFrame->mbDefPos = FALSE; 1293 pFrame->mbOverwriteState = TRUE; 1294 pFrame->mbInShow = TRUE; 1295 1296 // #i4715, save position 1297 RECT aRectPreMatrox, aRectPostMatrox; 1298 GetWindowRect( hWnd, &aRectPreMatrox ); 1299 1300 vcl::DeletionListener aDogTag( pFrame ); 1301 if( bNoActivate ) 1302 ShowWindow( hWnd, SW_SHOWNOACTIVATE ); 1303 else 1304 ShowWindow( hWnd, pFrame->mnShowState ); 1305 if( aDogTag.isDeleted() ) 1306 return; 1307 1308 if ( aSalShlData.mbWXP && pFrame->mbFloatWin && !(pFrame->mnStyle & SAL_FRAME_STYLE_NOSHADOW)) 1309 { 1310 // erase the window immediately to improve XP shadow effect 1311 // otherwise the shadow may appears long time before the rest of the window 1312 // especially when accessibility is on 1313 HDC dc = GetDC( hWnd ); 1314 RECT aRect; 1315 GetClientRect( hWnd, &aRect ); 1316 FillRect( dc, &aRect, (HBRUSH) (COLOR_MENU+1) ); // choose the menucolor, because it's mostly noticeable for menus 1317 ReleaseDC( hWnd, dc ); 1318 } 1319 1320 // #i4715, matrox centerpopup might have changed our position 1321 // reposition popups without caption (menus, dropdowns, tooltips) 1322 GetWindowRect( hWnd, &aRectPostMatrox ); 1323 if( (GetWindowStyle( hWnd ) & WS_POPUP) && 1324 !pFrame->mbCaption && 1325 (aRectPreMatrox.left != aRectPostMatrox.left || aRectPreMatrox.top != aRectPostMatrox.top) ) 1326 SetWindowPos( hWnd, 0, aRectPreMatrox.left, aRectPreMatrox.top, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE ); 1327 1328 if( aDogTag.isDeleted() ) 1329 return; 1330 Window *pClientWin = pFrame->GetWindow()->ImplGetClientWindow(); 1331 if ( pFrame->mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) ) 1332 pFrame->mnShowState = SW_SHOWNOACTIVATE; 1333 else 1334 pFrame->mnShowState = SW_SHOW; 1335 // Damit Taskleiste unter W98 auch gleich ausgeblendet wird 1336 if ( pFrame->mbPresentation ) 1337 { 1338 HWND hWndParent = ::GetParent( hWnd ); 1339 if ( hWndParent ) 1340 SetForegroundWindow( hWndParent ); 1341 SetForegroundWindow( hWnd ); 1342 } 1343 1344 pFrame->mbInShow = FALSE; 1345 pFrame->updateScreenNumber(); 1346 1347 // Direct Paint only, if we get the SolarMutx 1348 if ( ImplSalYieldMutexTryToAcquire() ) 1349 { 1350 UpdateWindow( hWnd ); 1351 ImplSalYieldMutexRelease(); 1352 } 1353 } 1354 else 1355 { 1356 // See also Bug #91813# and #68467# 1357 if ( pFrame->mbFullScreen && 1358 pFrame->mbPresentation && 1359 (aSalShlData.mnVersion < 500) && 1360 !::GetParent( hWnd ) ) 1361 { 1362 // Damit im Impress-Player in der Taskleiste nicht durch 1363 // einen Windows-Fehler hin- und wieder mal ein leerer 1364 // Button stehen bleibt, muessen wir hier die Taskleiste 1365 // etwas austricksen. Denn wenn wir im FullScreenMode sind 1366 // und das Fenster hiden kommt Windows anscheinend etwas aus 1367 // dem tritt und somit minimieren wir das Fenster damit es 1368 // nicht flackert 1369 ANIMATIONINFO aInfo; 1370 aInfo.cbSize = sizeof( aInfo ); 1371 SystemParametersInfo( SPI_GETANIMATION, 0, &aInfo, 0 ); 1372 if ( aInfo.iMinAnimate ) 1373 { 1374 int nOldAni = aInfo.iMinAnimate; 1375 aInfo.iMinAnimate = 0; 1376 SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 ); 1377 ShowWindow( pFrame->mhWnd, SW_SHOWMINNOACTIVE ); 1378 aInfo.iMinAnimate = nOldAni; 1379 SystemParametersInfo( SPI_SETANIMATION, 0, &aInfo, 0 ); 1380 } 1381 else 1382 ShowWindow( hWnd, SW_SHOWMINNOACTIVE ); 1383 ShowWindow( hWnd, SW_HIDE ); 1384 } 1385 else 1386 ShowWindow( hWnd, SW_HIDE ); 1387 } 1388 } 1389 1390 // ----------------------------------------------------------------------- 1391 1392 1393 void WinSalFrame::SetExtendedFrameStyle( SalExtStyle ) 1394 { 1395 } 1396 1397 // ----------------------------------------------------------------------- 1398 1399 void WinSalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate ) 1400 { 1401 // Post this Message to the window, because this only works 1402 // in the thread of the window, which has create this window. 1403 // We post this message to avoid deadlocks 1404 if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() ) 1405 ImplPostMessage( mhWnd, SAL_MSG_SHOW, bVisible, bNoActivate ); 1406 else 1407 ImplSalShow( mhWnd, bVisible, bNoActivate ); 1408 } 1409 1410 // ----------------------------------------------------------------------- 1411 1412 void WinSalFrame::Enable( sal_Bool bEnable ) 1413 { 1414 EnableWindow( mhWnd, bEnable ); 1415 } 1416 1417 // ----------------------------------------------------------------------- 1418 1419 void WinSalFrame::SetMinClientSize( long nWidth, long nHeight ) 1420 { 1421 mnMinWidth = nWidth; 1422 mnMinHeight = nHeight; 1423 } 1424 1425 void WinSalFrame::SetMaxClientSize( long nWidth, long nHeight ) 1426 { 1427 mnMaxWidth = nWidth; 1428 mnMaxHeight = nHeight; 1429 } 1430 1431 // ----------------------------------------------------------------------- 1432 1433 void WinSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, 1434 sal_uInt16 nFlags ) 1435 { 1436 sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0; 1437 if ( !bVisible ) 1438 { 1439 Window *pClientWin = GetWindow()->ImplGetClientWindow(); 1440 if ( mbFloatWin || ( pClientWin && (pClientWin->GetStyle() & WB_SYSTEMFLOATWIN) ) ) 1441 mnShowState = SW_SHOWNOACTIVATE; 1442 else 1443 mnShowState = SW_SHOWNORMAL; 1444 } 1445 else 1446 { 1447 if ( IsIconic( mhWnd ) || IsZoomed( mhWnd ) ) 1448 ShowWindow( mhWnd, SW_RESTORE ); 1449 } 1450 1451 sal_uInt16 nEvent = 0; 1452 UINT nPosSize = 0; 1453 RECT aClientRect, aWindowRect; 1454 GetClientRect( mhWnd, &aClientRect ); // x,y always 0,0, but width and height without border 1455 GetWindowRect( mhWnd, &aWindowRect ); // x,y in screen coordinates, width and height with border 1456 1457 if ( !(nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) ) 1458 nPosSize |= SWP_NOMOVE; 1459 else 1460 { 1461 //DBG_ASSERT( nX && nY, " Windowposition of (0,0) requested!" ); 1462 nEvent = SALEVENT_MOVE; 1463 } 1464 if ( !(nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) ) 1465 nPosSize |= SWP_NOSIZE; 1466 else 1467 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; 1468 1469 if ( !(nFlags & SAL_FRAME_POSSIZE_X) ) 1470 nX = aWindowRect.left; 1471 if ( !(nFlags & SAL_FRAME_POSSIZE_Y) ) 1472 nY = aWindowRect.top; 1473 if ( !(nFlags & SAL_FRAME_POSSIZE_WIDTH) ) 1474 nWidth = aClientRect.right-aClientRect.left; 1475 if ( !(nFlags & SAL_FRAME_POSSIZE_HEIGHT) ) 1476 nHeight = aClientRect.bottom-aClientRect.top; 1477 1478 // Calculate window size including the border 1479 RECT aWinRect; 1480 aWinRect.left = 0; 1481 aWinRect.right = (int)nWidth-1; 1482 aWinRect.top = 0; 1483 aWinRect.bottom = (int)nHeight-1; 1484 AdjustWindowRectEx( &aWinRect, GetWindowStyle( mhWnd ), 1485 FALSE, GetWindowExStyle( mhWnd ) ); 1486 nWidth = aWinRect.right - aWinRect.left + 1; 1487 nHeight = aWinRect.bottom - aWinRect.top + 1; 1488 1489 if ( !(nPosSize & SWP_NOMOVE) && ::GetParent( mhWnd ) ) 1490 { 1491 // --- RTL --- (mirror window pos) 1492 RECT aParentRect; 1493 GetClientRect( ImplGetParentHwnd( mhWnd ), &aParentRect ); 1494 if( Application::GetSettings().GetLayoutRTL() ) 1495 nX = (aParentRect.right - aParentRect.left) - nWidth-1 - nX; 1496 1497 //#110386#, do not transform coordinates for system child windows 1498 if( !(GetWindowStyle( mhWnd ) & WS_CHILD) ) 1499 { 1500 POINT aPt; 1501 aPt.x = nX; 1502 aPt.y = nY; 1503 1504 HWND parentHwnd = ImplGetParentHwnd( mhWnd ); 1505 WinSalFrame* pParentFrame = GetWindowPtr( parentHwnd ); 1506 if ( pParentFrame && pParentFrame->mnShowState == SW_SHOWMAXIMIZED ) 1507 { 1508 // #i42485#: parent will be shown maximized in which case 1509 // a ClientToScreen uses the wrong coordinates (i.e. those from the restore pos) 1510 // so use the (already updated) frame geometry for the transformation 1511 aPt.x += pParentFrame->maGeometry.nX; 1512 aPt.y += pParentFrame->maGeometry.nY; 1513 } 1514 else 1515 ClientToScreen( parentHwnd, &aPt ); 1516 1517 nX = aPt.x; 1518 nY = aPt.y; 1519 } 1520 } 1521 1522 // #i3338# to be conformant to UNIX we must position the client window, i.e. without the decoration 1523 // #i43250# if the position was read from the system (GetWindowRect(), see above), it must not be modified 1524 if ( nFlags & SAL_FRAME_POSSIZE_X ) 1525 nX += aWinRect.left; 1526 if ( nFlags & SAL_FRAME_POSSIZE_Y ) 1527 nY += aWinRect.top; 1528 1529 int nScreenX; 1530 int nScreenY; 1531 int nScreenWidth; 1532 int nScreenHeight; 1533 1534 1535 RECT aRect; 1536 ImplSalGetWorkArea( mhWnd, &aRect, NULL ); 1537 nScreenX = aRect.left; 1538 nScreenY = aRect.top; 1539 nScreenWidth = aRect.right-aRect.left; 1540 nScreenHeight = aRect.bottom-aRect.top; 1541 1542 if ( mbDefPos && (nPosSize & SWP_NOMOVE)) // we got no positioning request, so choose default position 1543 { 1544 // center window 1545 1546 HWND hWndParent = ::GetParent( mhWnd ); 1547 // Search for TopLevel Frame 1548 while ( hWndParent && (GetWindowStyle( hWndParent ) & WS_CHILD) ) 1549 hWndParent = ::GetParent( hWndParent ); 1550 // if the Window has a Parent, than center the window to 1551 // the parent, in the other case to the screen 1552 if ( hWndParent && !IsIconic( hWndParent ) && 1553 (GetWindowStyle( hWndParent ) & WS_VISIBLE) ) 1554 { 1555 RECT aParentRect; 1556 GetWindowRect( hWndParent, &aParentRect ); 1557 int nParentWidth = aParentRect.right-aParentRect.left; 1558 int nParentHeight = aParentRect.bottom-aParentRect.top; 1559 1560 // We don't center, when Parent is smaller than our window 1561 if ( (nParentWidth-GetSystemMetrics( SM_CXFIXEDFRAME ) <= nWidth) && 1562 (nParentHeight-GetSystemMetrics( SM_CYFIXEDFRAME ) <= nHeight) ) 1563 { 1564 int nOff = GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION ); 1565 nX = aParentRect.left+nOff; 1566 nY = aParentRect.top+nOff; 1567 } 1568 else 1569 { 1570 nX = (nParentWidth-nWidth)/2 + aParentRect.left; 1571 nY = (nParentHeight-nHeight)/2 + aParentRect.top; 1572 } 1573 } 1574 else 1575 { 1576 POINT pt; 1577 GetCursorPos( &pt ); 1578 RECT aRect; 1579 aRect.left = pt.x; 1580 aRect.top = pt.y; 1581 aRect.right = pt.x+2; 1582 aRect.bottom = pt.y+2; 1583 1584 // dualmonitor support: 1585 // Get screensize of the monitor with the mouse pointer 1586 ImplSalGetWorkArea( mhWnd, &aRect, &aRect ); 1587 1588 nX = ((aRect.right-aRect.left)-nWidth)/2 + aRect.left; 1589 nY = ((aRect.bottom-aRect.top)-nHeight)/2 + aRect.top; 1590 } 1591 1592 1593 //if ( bVisible ) 1594 // mbDefPos = FALSE; 1595 1596 mbDefPos = FALSE; // center only once 1597 nPosSize &= ~SWP_NOMOVE; // activate positioning 1598 nEvent = SALEVENT_MOVERESIZE; 1599 } 1600 1601 1602 // Adjust Window in the screen 1603 sal_Bool bCheckOffScreen = TRUE; 1604 1605 // but don't do this for floaters or ownerdraw windows that are currently moved interactively 1606 if( (mnStyle & SAL_FRAME_STYLE_FLOAT) && !(mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) 1607 bCheckOffScreen = FALSE; 1608 1609 if( mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION ) 1610 { 1611 // may be the window is currently being moved (mouse is captured), then no check is required 1612 if( mhWnd == ::GetCapture() ) 1613 bCheckOffScreen = FALSE; 1614 else 1615 bCheckOffScreen = TRUE; 1616 } 1617 1618 if( bCheckOffScreen ) 1619 { 1620 if ( nX+nWidth > nScreenX+nScreenWidth ) 1621 nX = (nScreenX+nScreenWidth) - nWidth; 1622 if ( nY+nHeight > nScreenY+nScreenHeight ) 1623 nY = (nScreenY+nScreenHeight) - nHeight; 1624 if ( nX < nScreenX ) 1625 nX = nScreenX; 1626 if ( nY < nScreenY ) 1627 nY = nScreenY; 1628 } 1629 1630 UINT nPosFlags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | nPosSize; 1631 // bring floating windows always to top 1632 if( !(mnStyle & SAL_FRAME_STYLE_FLOAT) ) 1633 nPosFlags |= SWP_NOZORDER; // do not change z-order 1634 1635 SetWindowPos( mhWnd, HWND_TOP, nX, nY, (int)nWidth, (int)nHeight, nPosFlags ); 1636 1637 UpdateFrameGeometry( mhWnd, this ); 1638 1639 // Notification -- really ??? 1640 if( nEvent ) 1641 CallCallback( nEvent, NULL ); 1642 } 1643 1644 // ----------------------------------------------------------------------- 1645 1646 static void ImplSetParentFrame( WinSalFrame* pThis, HWND hNewParentWnd, sal_Bool bAsChild ) 1647 { 1648 // save hwnd, will be overwritten in WM_CREATE during createwindow 1649 HWND hWndOld = pThis->mhWnd; 1650 HWND hWndOldParent = ::GetParent( hWndOld ); 1651 SalData* pSalData = GetSalData(); 1652 1653 if( hNewParentWnd == hWndOldParent ) 1654 return; 1655 1656 ::std::vector< WinSalFrame* > children; 1657 ::std::vector< WinSalObject* > systemChildren; 1658 1659 // search child windows 1660 WinSalFrame *pFrame = pSalData->mpFirstFrame; 1661 while( pFrame ) 1662 { 1663 HWND hWndParent = ::GetParent( pFrame->mhWnd ); 1664 if( pThis->mhWnd == hWndParent ) 1665 children.push_back( pFrame ); 1666 pFrame = pFrame->mpNextFrame; 1667 } 1668 1669 // search system child windows (plugins etc.) 1670 WinSalObject *pObject = pSalData->mpFirstObject; 1671 while( pObject ) 1672 { 1673 HWND hWndParent = ::GetParent( pObject->mhWnd ); 1674 if( pThis->mhWnd == hWndParent ) 1675 systemChildren.push_back( pObject ); 1676 pObject = pObject->mpNextObject; 1677 } 1678 1679 sal_Bool bNeedGraphics = pThis->mbGraphics; 1680 sal_Bool bNeedCacheDC = FALSE; 1681 1682 HFONT hFont = NULL; 1683 HPEN hPen = NULL; 1684 HBRUSH hBrush = NULL; 1685 1686 #if OSL_DEBUG_LEVEL > 0 1687 int oldCount = pSalData->mnCacheDCInUse; 1688 (void)oldCount; 1689 #endif 1690 1691 // Release Cache DC 1692 if ( pThis->mpGraphics2 && 1693 pThis->mpGraphics2->getHDC() ) 1694 { 1695 // save current gdi objects before hdc is gone 1696 hFont = (HFONT) GetCurrentObject( pThis->mpGraphics2->getHDC(), OBJ_FONT); 1697 hPen = (HPEN) GetCurrentObject( pThis->mpGraphics2->getHDC(), OBJ_PEN); 1698 hBrush = (HBRUSH) GetCurrentObject( pThis->mpGraphics2->getHDC(), OBJ_BRUSH); 1699 pThis->ReleaseGraphics( pThis->mpGraphics2 ); 1700 1701 // recreate cache dc only if it was destroyed 1702 bNeedCacheDC = TRUE; 1703 } 1704 1705 // destroy saved DC 1706 if ( pThis->mpGraphics ) 1707 { 1708 if ( pThis->mpGraphics->mhDefPal ) 1709 SelectPalette( pThis->mpGraphics->getHDC(), pThis->mpGraphics->mhDefPal, TRUE ); 1710 ImplSalDeInitGraphics( pThis->mpGraphics ); 1711 ReleaseDC( pThis->mhWnd, pThis->mpGraphics->getHDC() ); 1712 } 1713 1714 // create a new hwnd with the same styles 1715 HWND hWndParent = hNewParentWnd; 1716 // forward to main thread 1717 HWND hWnd = (HWND) ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, 1718 bAsChild ? SAL_MSG_RECREATECHILDHWND : SAL_MSG_RECREATEHWND, 1719 (WPARAM) hWndParent, (LPARAM)pThis->mhWnd ); 1720 1721 // succeeded ? 1722 DBG_ASSERT( IsWindow( hWnd ), "WinSalFrame::SetParent not successful"); 1723 1724 // recreate DCs 1725 if( bNeedGraphics ) 1726 { 1727 if( pThis->mpGraphics2 ) 1728 { 1729 pThis->mpGraphics2->mhWnd = hWnd; 1730 1731 if( bNeedCacheDC ) 1732 { 1733 // re-create cached DC 1734 HDC hDC = (HDC)ImplSendMessage( pSalData->mpFirstInstance->mhComWnd, 1735 SAL_MSG_GETDC, 1736 (WPARAM) hWnd, 0 ); 1737 if ( hDC ) 1738 { 1739 pThis->mpGraphics2->setHDC(hDC); 1740 if ( pSalData->mhDitherPal ) 1741 { 1742 pThis->mpGraphics2->mhDefPal = SelectPalette( hDC, pSalData->mhDitherPal, TRUE ); 1743 RealizePalette( hDC ); 1744 } 1745 ImplSalInitGraphics( pThis->mpGraphics2 ); 1746 1747 // re-select saved gdi objects 1748 if( hFont ) 1749 SelectObject( hDC, hFont ); 1750 if( hPen ) 1751 SelectObject( hDC, hPen ); 1752 if( hBrush ) 1753 SelectObject( hDC, hBrush ); 1754 1755 pThis->mbGraphics = TRUE; 1756 1757 pSalData->mnCacheDCInUse++; 1758 1759 DBG_ASSERT( oldCount == pSalData->mnCacheDCInUse, "WinSalFrame::SetParent() hDC count corrupted"); 1760 } 1761 } 1762 } 1763 1764 if( pThis->mpGraphics ) 1765 { 1766 // re-create DC 1767 pThis->mpGraphics->mhWnd = hWnd; 1768 pThis->mpGraphics->setHDC( GetDC( hWnd ) ); 1769 if ( GetSalData()->mhDitherPal ) 1770 { 1771 pThis->mpGraphics->mhDefPal = SelectPalette( pThis->mpGraphics->getHDC(), GetSalData()->mhDitherPal, TRUE ); 1772 RealizePalette( pThis->mpGraphics->getHDC() ); 1773 } 1774 ImplSalInitGraphics( pThis->mpGraphics ); 1775 pThis->mbGraphics = TRUE; 1776 } 1777 } 1778 1779 1780 // TODO: add SetParent() call for SalObjects 1781 DBG_ASSERT( systemChildren.empty(), "WinSalFrame::SetParent() parent of living system child window will be destroyed!"); 1782 1783 // reparent children before old parent is destroyed 1784 for( ::std::vector< WinSalFrame* >::iterator iChild = children.begin(); iChild != children.end(); iChild++ ) 1785 ImplSetParentFrame( *iChild, hWnd, FALSE ); 1786 1787 children.clear(); 1788 systemChildren.clear(); 1789 1790 // Now destroy original HWND in the thread where it was created. 1791 ImplSendMessage( GetSalData()->mpFirstInstance->mhComWnd, 1792 SAL_MSG_DESTROYHWND, (WPARAM) 0, (LPARAM)hWndOld); 1793 } 1794 1795 // ----------------------------------------------------------------------- 1796 1797 void WinSalFrame::SetParent( SalFrame* pNewParent ) 1798 { 1799 WinSalFrame::mbInReparent = TRUE; 1800 ImplSetParentFrame( this, static_cast<WinSalFrame*>(pNewParent)->mhWnd, FALSE ); 1801 WinSalFrame::mbInReparent = FALSE; 1802 } 1803 1804 bool WinSalFrame::SetPluginParent( SystemParentData* pNewParent ) 1805 { 1806 if ( pNewParent->hWnd == 0 ) 1807 { 1808 pNewParent->hWnd = GetDesktopWindow(); 1809 } 1810 1811 WinSalFrame::mbInReparent = TRUE; 1812 ImplSetParentFrame( this, pNewParent->hWnd, TRUE ); 1813 WinSalFrame::mbInReparent = FALSE; 1814 return true; 1815 } 1816 1817 1818 // ----------------------------------------------------------------------- 1819 1820 void WinSalFrame::GetWorkArea( Rectangle &rRect ) 1821 { 1822 RECT aRect; 1823 ImplSalGetWorkArea( mhWnd, &aRect, NULL ); 1824 rRect.nLeft = aRect.left; 1825 rRect.nRight = aRect.right-1; 1826 rRect.nTop = aRect.top; 1827 rRect.nBottom = aRect.bottom-1; 1828 } 1829 1830 // ----------------------------------------------------------------------- 1831 1832 void WinSalFrame::GetClientSize( long& rWidth, long& rHeight ) 1833 { 1834 rWidth = maGeometry.nWidth; 1835 rHeight = maGeometry.nHeight; 1836 } 1837 1838 // ----------------------------------------------------------------------- 1839 1840 void WinSalFrame::SetWindowState( const SalFrameState* pState ) 1841 { 1842 // Wir testen, ob das Fenster ueberhaupt auf den Bildschirm passt, damit 1843 // nicht wenn die Bildschirm-Aufloesung geaendert wurde, das Fenster aus 1844 // diesem herausragt 1845 int nX; 1846 int nY; 1847 int nWidth; 1848 int nHeight; 1849 int nScreenX; 1850 int nScreenY; 1851 int nScreenWidth; 1852 int nScreenHeight; 1853 1854 RECT aRect; 1855 ImplSalGetWorkArea( mhWnd, &aRect, NULL ); 1856 // #102500# allow some overlap, the window could have been made a little larger than the physical screen 1857 nScreenX = aRect.left-10; 1858 nScreenY = aRect.top-10; 1859 nScreenWidth = aRect.right-aRect.left+20; 1860 nScreenHeight = aRect.bottom-aRect.top+20; 1861 1862 UINT nPosSize = 0; 1863 RECT aWinRect; 1864 GetWindowRect( mhWnd, &aWinRect ); 1865 1866 // to be consistent with Unix, the frame state is without(!) decoration 1867 // ->add the decoration 1868 RECT aRect2 = aWinRect; 1869 AdjustWindowRectEx( &aRect2, GetWindowStyle( mhWnd ), 1870 FALSE, GetWindowExStyle( mhWnd ) ); 1871 long nTopDeco = abs( aWinRect.top - aRect2.top ); 1872 long nLeftDeco = abs( aWinRect.left - aRect2.left ); 1873 long nBottomDeco = abs( aWinRect.bottom - aRect2.bottom ); 1874 long nRightDeco = abs( aWinRect.right - aRect2.right ); 1875 1876 // Fenster-Position/Groesse in den Bildschirm einpassen 1877 if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y)) ) 1878 nPosSize |= SWP_NOMOVE; 1879 if ( !(pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT)) ) 1880 nPosSize |= SWP_NOSIZE; 1881 if ( pState->mnMask & SAL_FRAMESTATE_MASK_X ) 1882 nX = (int)pState->mnX - nLeftDeco; 1883 else 1884 nX = aWinRect.left; 1885 if ( pState->mnMask & SAL_FRAMESTATE_MASK_Y ) 1886 nY = (int)pState->mnY - nTopDeco; 1887 else 1888 nY = aWinRect.top; 1889 if ( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH ) 1890 nWidth = (int)pState->mnWidth + nLeftDeco + nRightDeco; 1891 else 1892 nWidth = aWinRect.right-aWinRect.left; 1893 if ( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT ) 1894 nHeight = (int)pState->mnHeight + nTopDeco + nBottomDeco; 1895 else 1896 nHeight = aWinRect.bottom-aWinRect.top; 1897 1898 // Adjust Window in the screen: 1899 // if it does not fit into the screen do nothing, i.e. default pos/size will be used 1900 // if there is an overlap with the screen border move the window while keeping its size 1901 1902 if( nWidth > nScreenWidth || nHeight > nScreenHeight ) 1903 nPosSize |= (SWP_NOMOVE | SWP_NOSIZE); 1904 1905 if ( nX+nWidth > nScreenX+nScreenWidth ) 1906 nX = (nScreenX+nScreenWidth) - nWidth; 1907 if ( nY+nHeight > nScreenY+nScreenHeight ) 1908 nY = (nScreenY+nScreenHeight) - nHeight; 1909 if ( nX < nScreenX ) 1910 nX = nScreenX; 1911 if ( nY < nScreenY ) 1912 nY = nScreenY; 1913 1914 // Restore-Position setzen 1915 WINDOWPLACEMENT aPlacement; 1916 aPlacement.length = sizeof( aPlacement ); 1917 GetWindowPlacement( mhWnd, &aPlacement ); 1918 1919 // Status setzen 1920 sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0; 1921 sal_Bool bUpdateHiddenFramePos = FALSE; 1922 if ( !bVisible ) 1923 { 1924 aPlacement.showCmd = SW_HIDE; 1925 1926 if ( mbOverwriteState ) 1927 { 1928 if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE ) 1929 { 1930 if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED ) 1931 mnShowState = SW_SHOWMINIMIZED; 1932 else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED ) 1933 { 1934 mnShowState = SW_SHOWMAXIMIZED; 1935 bUpdateHiddenFramePos = TRUE; 1936 } 1937 else if ( pState->mnState & SAL_FRAMESTATE_NORMAL ) 1938 mnShowState = SW_SHOWNORMAL; 1939 } 1940 } 1941 } 1942 else 1943 { 1944 if ( pState->mnMask & SAL_FRAMESTATE_MASK_STATE ) 1945 { 1946 if ( pState->mnState & SAL_FRAMESTATE_MINIMIZED ) 1947 { 1948 if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED ) 1949 aPlacement.flags |= WPF_RESTORETOMAXIMIZED; 1950 aPlacement.showCmd = SW_SHOWMINIMIZED; 1951 } 1952 else if ( pState->mnState & SAL_FRAMESTATE_MAXIMIZED ) 1953 aPlacement.showCmd = SW_SHOWMAXIMIZED; 1954 else if ( pState->mnState & SAL_FRAMESTATE_NORMAL ) 1955 aPlacement.showCmd = SW_RESTORE; 1956 } 1957 } 1958 1959 // if a window is neither minimized nor maximized or need not be 1960 // positioned visibly (that is in visible state), do not use 1961 // SetWindowPlacement since it calculates including the TaskBar 1962 if ( !IsIconic( mhWnd ) && !IsZoomed( mhWnd ) && 1963 (!bVisible || (aPlacement.showCmd == SW_RESTORE)) ) 1964 { 1965 if( bUpdateHiddenFramePos ) 1966 { 1967 RECT aStateRect; 1968 aStateRect.left = nX; 1969 aStateRect.top = nY; 1970 aStateRect.right = nX+nWidth; 1971 aStateRect.bottom = nY+nHeight; 1972 // #96084 set a useful internal window size because 1973 // the window will not be maximized (and the size updated) before show() 1974 SetMaximizedFrameGeometry( mhWnd, this, &aStateRect ); 1975 SetWindowPos( mhWnd, 0, 1976 maGeometry.nX, maGeometry.nY, maGeometry.nWidth, maGeometry.nHeight, 1977 SWP_NOZORDER | SWP_NOACTIVATE | nPosSize ); 1978 } 1979 else 1980 SetWindowPos( mhWnd, 0, 1981 nX, nY, nWidth, nHeight, 1982 SWP_NOZORDER | SWP_NOACTIVATE | nPosSize ); 1983 } 1984 else 1985 { 1986 if( !(nPosSize & (SWP_NOMOVE|SWP_NOSIZE)) ) 1987 { 1988 aPlacement.rcNormalPosition.left = nX-nScreenX; 1989 aPlacement.rcNormalPosition.top = nY-nScreenY; 1990 aPlacement.rcNormalPosition.right = nX+nWidth-nScreenX; 1991 aPlacement.rcNormalPosition.bottom = nY+nHeight-nScreenY; 1992 } 1993 SetWindowPlacement( mhWnd, &aPlacement ); 1994 } 1995 1996 if( !(nPosSize & SWP_NOMOVE) ) 1997 mbDefPos = FALSE; // window was positioned 1998 } 1999 2000 // ----------------------------------------------------------------------- 2001 2002 sal_Bool WinSalFrame::GetWindowState( SalFrameState* pState ) 2003 { 2004 if ( maState.mnWidth && maState.mnHeight ) 2005 { 2006 *pState = maState; 2007 // #94144# allow Minimize again, should be masked out when read from configuration 2008 // 91625 - Don't save minimize 2009 //if ( !(pState->mnState & SAL_FRAMESTATE_MAXIMIZED) ) 2010 if ( !(pState->mnState & (SAL_FRAMESTATE_MINIMIZED | SAL_FRAMESTATE_MAXIMIZED)) ) 2011 pState->mnState |= SAL_FRAMESTATE_NORMAL; 2012 return TRUE; 2013 } 2014 2015 return FALSE; 2016 } 2017 2018 // ----------------------------------------------------------------------- 2019 2020 void WinSalFrame::SetScreenNumber( unsigned int nNewScreen ) 2021 { 2022 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem()); 2023 if( pSys ) 2024 { 2025 const std::vector<WinSalSystem::DisplayMonitor>& rMonitors = 2026 pSys->getMonitors(); 2027 size_t nMon = rMonitors.size(); 2028 if( nNewScreen < nMon ) 2029 { 2030 Point aOldMonPos, aNewMonPos( rMonitors[nNewScreen].m_aArea.TopLeft() ); 2031 Point aCurPos( maGeometry.nX, maGeometry.nY ); 2032 for( size_t i = 0; i < nMon; i++ ) 2033 { 2034 if( rMonitors[i].m_aArea.IsInside( aCurPos ) ) 2035 { 2036 aOldMonPos = rMonitors[i].m_aArea.TopLeft(); 2037 break; 2038 } 2039 } 2040 mnDisplay = nNewScreen; 2041 maGeometry.nScreenNumber = nNewScreen; 2042 SetPosSize( aNewMonPos.X() + (maGeometry.nX - aOldMonPos.X()), 2043 aNewMonPos.Y() + (maGeometry.nY - aOldMonPos.Y()), 2044 0, 0, 2045 SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); 2046 } 2047 } 2048 } 2049 2050 // ----------------------------------------------------------------------- 2051 2052 void WinSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay ) 2053 { 2054 if ( (mbFullScreen == bFullScreen) && (!bFullScreen || (mnDisplay == nDisplay)) ) 2055 return; 2056 2057 mbFullScreen = bFullScreen; 2058 mnDisplay = nDisplay; 2059 2060 if ( bFullScreen ) 2061 { 2062 // Damit Taskleiste von Windows ausgeblendet wird 2063 DWORD nExStyle = GetWindowExStyle( mhWnd ); 2064 if ( nExStyle & WS_EX_TOOLWINDOW ) 2065 { 2066 mbFullScreenToolWin = TRUE; 2067 nExStyle &= ~WS_EX_TOOLWINDOW; 2068 SetWindowExStyle( mhWnd, nExStyle ); 2069 } 2070 // save old position 2071 GetWindowRect( mhWnd, &maFullScreenRect ); 2072 2073 // save show state 2074 mnFullScreenShowState = mnShowState; 2075 if ( !(GetWindowStyle( mhWnd ) & WS_VISIBLE) ) 2076 mnShowState = SW_SHOW; 2077 2078 // set window to screen size 2079 ImplSalFrameFullScreenPos( this, TRUE ); 2080 } 2081 else 2082 { 2083 // wenn ShowState wieder hergestellt werden muss, hiden wir zuerst 2084 // das Fenster, damit es nicht so sehr flackert 2085 sal_Bool bVisible = (GetWindowStyle( mhWnd ) & WS_VISIBLE) != 0; 2086 if ( bVisible && (mnShowState != mnFullScreenShowState) ) 2087 ShowWindow( mhWnd, SW_HIDE ); 2088 2089 if ( mbFullScreenToolWin ) 2090 SetWindowExStyle( mhWnd, GetWindowExStyle( mhWnd ) | WS_EX_TOOLWINDOW ); 2091 mbFullScreenToolWin = FALSE; 2092 2093 SetWindowPos( mhWnd, 0, 2094 maFullScreenRect.left, 2095 maFullScreenRect.top, 2096 maFullScreenRect.right-maFullScreenRect.left, 2097 maFullScreenRect.bottom-maFullScreenRect.top, 2098 SWP_NOZORDER | SWP_NOACTIVATE ); 2099 2100 // restore show state 2101 if ( mnShowState != mnFullScreenShowState ) 2102 { 2103 mnShowState = mnFullScreenShowState; 2104 if ( bVisible ) 2105 { 2106 mbInShow = TRUE; 2107 ShowWindow( mhWnd, mnShowState ); 2108 mbInShow = FALSE; 2109 UpdateWindow( mhWnd ); 2110 } 2111 } 2112 } 2113 } 2114 2115 // ----------------------------------------------------------------------- 2116 2117 void WinSalFrame::StartPresentation( sal_Bool bStart ) 2118 { 2119 if ( mbPresentation == bStart ) 2120 return; 2121 2122 mbPresentation = bStart; 2123 2124 SalData* pSalData = GetSalData(); 2125 if ( bStart ) 2126 { 2127 if ( !pSalData->mpSageEnableProc ) 2128 { 2129 if ( pSalData->mnSageStatus != DISABLE_AGENT ) 2130 { 2131 OFSTRUCT aOS; 2132 OpenFile( "SAGE.DLL", &aOS, OF_EXIST ); 2133 2134 if ( !aOS.nErrCode ) 2135 { 2136 oslModule mhSageInst = osl_loadAsciiModule( aOS.szPathName, SAL_LOADMODULE_DEFAULT ); 2137 pSalData->mpSageEnableProc = (SysAgt_Enable_PROC)osl_getAsciiFunctionSymbol( mhSageInst, "System_Agent_Enable" ); 2138 } 2139 else 2140 pSalData->mnSageStatus = DISABLE_AGENT; 2141 } 2142 } 2143 2144 if ( pSalData->mpSageEnableProc ) 2145 { 2146 pSalData->mnSageStatus = pSalData->mpSageEnableProc( GET_AGENT_STATUS ); 2147 if ( pSalData->mnSageStatus == ENABLE_AGENT ) 2148 pSalData->mpSageEnableProc( DISABLE_AGENT ); 2149 } 2150 2151 // Bildschirmschoner ausschalten, wenn Praesentation laueft 2152 SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0, 2153 &(pSalData->mbScrSvrEnabled), 0 ); 2154 if ( pSalData->mbScrSvrEnabled ) 2155 SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, FALSE, 0, 0 ); 2156 } 2157 else 2158 { 2159 // Bildschirmschoner wieder einschalten 2160 if ( pSalData->mbScrSvrEnabled ) 2161 SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, pSalData->mbScrSvrEnabled, 0, 0 ); 2162 2163 // Systemagenten wieder aktivieren 2164 if ( pSalData->mnSageStatus == ENABLE_AGENT ) 2165 pSalData->mpSageEnableProc( pSalData->mnSageStatus ); 2166 } 2167 } 2168 2169 // ----------------------------------------------------------------------- 2170 2171 void WinSalFrame::SetAlwaysOnTop( sal_Bool bOnTop ) 2172 { 2173 HWND hWnd; 2174 if ( bOnTop ) 2175 hWnd = HWND_TOPMOST; 2176 else 2177 hWnd = HWND_NOTOPMOST; 2178 SetWindowPos( mhWnd, hWnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE ); 2179 } 2180 2181 // ----------------------------------------------------------------------- 2182 2183 static void ImplSalToTop( HWND hWnd, sal_uInt16 nFlags ) 2184 { 2185 WinSalFrame* pToTopFrame = GetWindowPtr( hWnd ); 2186 if( pToTopFrame && (pToTopFrame->mnStyle & SAL_FRAME_STYLE_SYSTEMCHILD) != 0 ) 2187 BringWindowToTop( hWnd ); 2188 2189 if ( nFlags & SAL_FRAME_TOTOP_FOREGROUNDTASK ) 2190 { 2191 // This magic code is necessary to connect the input focus of the 2192 // current window thread and the thread which owns the window that 2193 // should be the new foreground window. 2194 HWND hCurrWnd = GetForegroundWindow(); 2195 DWORD myThreadID = GetCurrentThreadId(); 2196 DWORD currThreadID = GetWindowThreadProcessId(hCurrWnd,NULL); 2197 AttachThreadInput(myThreadID, currThreadID,TRUE); 2198 SetForegroundWindow(hWnd); 2199 AttachThreadInput(myThreadID,currThreadID,FALSE); 2200 } 2201 2202 if ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN ) 2203 { 2204 HWND hIconicWnd = hWnd; 2205 while ( hIconicWnd ) 2206 { 2207 if ( IsIconic( hIconicWnd ) ) 2208 { 2209 WinSalFrame* pFrame = GetWindowPtr( hIconicWnd ); 2210 if ( pFrame ) 2211 { 2212 if ( GetWindowPtr( hWnd )->mbRestoreMaximize ) 2213 ShowWindow( hIconicWnd, SW_MAXIMIZE ); 2214 else 2215 ShowWindow( hIconicWnd, SW_RESTORE ); 2216 } 2217 else 2218 ShowWindow( hIconicWnd, SW_RESTORE ); 2219 } 2220 2221 hIconicWnd = ::GetParent( hIconicWnd ); 2222 } 2223 } 2224 2225 if ( !IsIconic( hWnd ) && IsWindowVisible( hWnd ) ) 2226 { 2227 SetFocus( hWnd ); 2228 2229 // Windows behauptet oefters mal, das man den Focus hat, obwohl 2230 // man diesen nicht hat. Wenn dies der Fall ist, dann versuchen 2231 // wir diesen auch ganz richtig zu bekommen. 2232 if ( ::GetFocus() == hWnd ) 2233 SetForegroundWindow( hWnd ); 2234 } 2235 } 2236 2237 // ----------------------------------------------------------------------- 2238 2239 void WinSalFrame::ToTop( sal_uInt16 nFlags ) 2240 { 2241 nFlags &= ~SAL_FRAME_TOTOP_GRABFOCUS; // this flag is not needed on win32 2242 // Post this Message to the window, because this only works 2243 // in the thread of the window, which has create this window. 2244 // We post this message to avoid deadlocks 2245 if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() ) 2246 ImplPostMessage( mhWnd, SAL_MSG_TOTOP, nFlags, 0 ); 2247 else 2248 ImplSalToTop( mhWnd, nFlags ); 2249 } 2250 2251 // ----------------------------------------------------------------------- 2252 2253 void WinSalFrame::SetPointer( PointerStyle ePointerStyle ) 2254 { 2255 struct ImplPtrData 2256 { 2257 HCURSOR mhCursor; 2258 LPCSTR mnSysId; 2259 UINT mnOwnId; 2260 }; 2261 2262 static ImplPtrData aImplPtrTab[POINTER_COUNT] = 2263 { 2264 { 0, IDC_ARROW, 0 }, // POINTER_ARROW 2265 { 0, 0, SAL_RESID_POINTER_NULL }, // POINTER_NULL 2266 { 0, IDC_WAIT, 0 }, // POINTER_WAIT 2267 { 0, IDC_IBEAM, 0 }, // POINTER_TEXT 2268 { 0, IDC_HELP, 0 }, // POINTER_HELP 2269 { 0, 0, SAL_RESID_POINTER_CROSS }, // POINTER_CROSS 2270 { 0, 0, SAL_RESID_POINTER_MOVE }, // POINTER_MOVE 2271 { 0, IDC_SIZENS, 0 }, // POINTER_NSIZE 2272 { 0, IDC_SIZENS, 0 }, // POINTER_SSIZE 2273 { 0, IDC_SIZEWE, 0 }, // POINTER_WSIZE 2274 { 0, IDC_SIZEWE, 0 }, // POINTER_ESIZE 2275 { 0, IDC_SIZENWSE, 0 }, // POINTER_NWSIZE 2276 { 0, IDC_SIZENESW, 0 }, // POINTER_NESIZE 2277 { 0, IDC_SIZENESW, 0 }, // POINTER_SWSIZE 2278 { 0, IDC_SIZENWSE, 0 }, // POINTER_SESIZE 2279 { 0, IDC_SIZENS, 0 }, // POINTER_WINDOW_NSIZE 2280 { 0, IDC_SIZENS, 0 }, // POINTER_WINDOW_SSIZE 2281 { 0, IDC_SIZEWE, 0 }, // POINTER_WINDOW_WSIZE 2282 { 0, IDC_SIZEWE, 0 }, // POINTER_WINDOW_ESIZE 2283 { 0, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_NWSIZE 2284 { 0, IDC_SIZENESW, 0 }, // POINTER_WINDOW_NESIZE 2285 { 0, IDC_SIZENESW, 0 }, // POINTER_WINDOW_SWSIZE 2286 { 0, IDC_SIZENWSE, 0 }, // POINTER_WINDOW_SESIZE 2287 { 0, 0, SAL_RESID_POINTER_HSPLIT }, // POINTER_HSPLIT 2288 { 0, 0, SAL_RESID_POINTER_VSPLIT }, // POINTER_VSPLIT 2289 { 0, 0, SAL_RESID_POINTER_HSIZEBAR }, // POINTER_HSIZEBAR 2290 { 0, 0, SAL_RESID_POINTER_VSIZEBAR }, // POINTER_VSIZEBAR 2291 { 0, 0, SAL_RESID_POINTER_HAND }, // POINTER_HAND 2292 { 0, 0, SAL_RESID_POINTER_REFHAND }, // POINTER_REFHAND 2293 { 0, 0, SAL_RESID_POINTER_PEN }, // POINTER_PEN 2294 { 0, 0, SAL_RESID_POINTER_MAGNIFY }, // POINTER_MAGNIFY 2295 { 0, 0, SAL_RESID_POINTER_FILL }, // POINTER_FILL 2296 { 0, 0, SAL_RESID_POINTER_ROTATE }, // POINTER_ROTATE 2297 { 0, 0, SAL_RESID_POINTER_HSHEAR }, // POINTER_HSHEAR 2298 { 0, 0, SAL_RESID_POINTER_VSHEAR }, // POINTER_VSHEAR 2299 { 0, 0, SAL_RESID_POINTER_MIRROR }, // POINTER_MIRROR 2300 { 0, 0, SAL_RESID_POINTER_CROOK }, // POINTER_CROOK 2301 { 0, 0, SAL_RESID_POINTER_CROP }, // POINTER_CROP 2302 { 0, 0, SAL_RESID_POINTER_MOVEPOINT }, // POINTER_MOVEPOINT 2303 { 0, 0, SAL_RESID_POINTER_MOVEBEZIERWEIGHT }, // POINTER_MOVEBEZIERWEIGHT 2304 { 0, 0, SAL_RESID_POINTER_MOVEDATA }, // POINTER_MOVEDATA 2305 { 0, 0, SAL_RESID_POINTER_COPYDATA }, // POINTER_COPYDATA 2306 { 0, 0, SAL_RESID_POINTER_LINKDATA }, // POINTER_LINKDATA 2307 { 0, 0, SAL_RESID_POINTER_MOVEDATALINK }, // POINTER_MOVEDATALINK 2308 { 0, 0, SAL_RESID_POINTER_COPYDATALINK }, // POINTER_COPYDATALINK 2309 { 0, 0, SAL_RESID_POINTER_MOVEFILE }, // POINTER_MOVEFILE 2310 { 0, 0, SAL_RESID_POINTER_COPYFILE }, // POINTER_COPYFILE 2311 { 0, 0, SAL_RESID_POINTER_LINKFILE }, // POINTER_LINKFILE 2312 { 0, 0, SAL_RESID_POINTER_MOVEFILELINK }, // POINTER_MOVEFILELINK 2313 { 0, 0, SAL_RESID_POINTER_COPYFILELINK }, // POINTER_COPYFILELINK 2314 { 0, 0, SAL_RESID_POINTER_MOVEFILES }, // POINTER_MOVEFILES 2315 { 0, 0, SAL_RESID_POINTER_COPYFILES }, // POINTER_COPYFILES 2316 { 0, 0, SAL_RESID_POINTER_NOTALLOWED }, // POINTER_NOTALLOWED 2317 { 0, 0, SAL_RESID_POINTER_DRAW_LINE }, // POINTER_DRAW_LINE 2318 { 0, 0, SAL_RESID_POINTER_DRAW_RECT }, // POINTER_DRAW_RECT 2319 { 0, 0, SAL_RESID_POINTER_DRAW_POLYGON }, // POINTER_DRAW_POLYGON 2320 { 0, 0, SAL_RESID_POINTER_DRAW_BEZIER }, // POINTER_DRAW_BEZIER 2321 { 0, 0, SAL_RESID_POINTER_DRAW_ARC }, // POINTER_DRAW_ARC 2322 { 0, 0, SAL_RESID_POINTER_DRAW_PIE }, // POINTER_DRAW_PIE 2323 { 0, 0, SAL_RESID_POINTER_DRAW_CIRCLECUT }, // POINTER_DRAW_CIRCLECUT 2324 { 0, 0, SAL_RESID_POINTER_DRAW_ELLIPSE }, // POINTER_DRAW_ELLIPSE 2325 { 0, 0, SAL_RESID_POINTER_DRAW_FREEHAND }, // POINTER_DRAW_FREEHAND 2326 { 0, 0, SAL_RESID_POINTER_DRAW_CONNECT }, // POINTER_DRAW_CONNECT 2327 { 0, 0, SAL_RESID_POINTER_DRAW_TEXT }, // POINTER_DRAW_TEXT 2328 { 0, 0, SAL_RESID_POINTER_DRAW_CAPTION }, // POINTER_DRAW_CAPTION 2329 { 0, 0, SAL_RESID_POINTER_CHART }, // POINTER_CHART 2330 { 0, 0, SAL_RESID_POINTER_DETECTIVE }, // POINTER_DETECTIVE 2331 { 0, 0, SAL_RESID_POINTER_PIVOT_COL }, // POINTER_PIVOT_COL 2332 { 0, 0, SAL_RESID_POINTER_PIVOT_ROW }, // POINTER_PIVOT_ROW 2333 { 0, 0, SAL_RESID_POINTER_PIVOT_FIELD }, // POINTER_PIVOT_FIELD 2334 { 0, 0, SAL_RESID_POINTER_CHAIN }, // POINTER_CHAIN 2335 { 0, 0, SAL_RESID_POINTER_CHAIN_NOTALLOWED }, // POINTER_CHAIN_NOTALLOWED 2336 { 0, 0, SAL_RESID_POINTER_TIMEEVENT_MOVE }, // POINTER_TIMEEVENT_MOVE 2337 { 0, 0, SAL_RESID_POINTER_TIMEEVENT_SIZE }, // POINTER_TIMEEVENT_SIZE 2338 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_N }, // POINTER_AUTOSCROLL_N 2339 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_S }, // POINTER_AUTOSCROLL_S 2340 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_W }, // POINTER_AUTOSCROLL_W 2341 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_E }, // POINTER_AUTOSCROLL_E 2342 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NW }, // POINTER_AUTOSCROLL_NW 2343 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NE }, // POINTER_AUTOSCROLL_NE 2344 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SW }, // POINTER_AUTOSCROLL_SW 2345 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_SE }, // POINTER_AUTOSCROLL_SE 2346 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NS }, // POINTER_AUTOSCROLL_NS 2347 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_WE }, // POINTER_AUTOSCROLL_WE 2348 { 0, 0, SAL_RESID_POINTER_AUTOSCROLL_NSWE }, // POINTER_AUTOSCROLL_NSWE 2349 { 0, 0, SAL_RESID_POINTER_AIRBRUSH }, // POINTER_AIRBRUSH 2350 { 0, 0, SAL_RESID_POINTER_TEXT_VERTICAL }, // POINTER_TEXT_VERTICAL 2351 { 0, 0, SAL_RESID_POINTER_PIVOT_DELETE }, // POINTER_PIVOT_DELETE 2352 2353 // --> FME 2004-07-30 #i32329# Enhanced table selection 2354 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_S }, // POINTER_TAB_SELECT_S 2355 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_E }, // POINTER_TAB_SELECT_E 2356 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SE }, // POINTER_TAB_SELECT_SE 2357 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_W }, // POINTER_TAB_SELECT_W 2358 { 0, 0, SAL_RESID_POINTER_TAB_SELECT_SW }, // POINTER_TAB_SELECT_SW 2359 // <-- 2360 2361 // --> FME 2004-08-16 #i20119# Paintbrush tool 2362 { 0, 0, SAL_RESID_POINTER_PAINTBRUSH } // POINTER_PAINTBRUSH 2363 // <-- 2364 2365 }; 2366 2367 #if POINTER_COUNT != 94 2368 #error New Pointer must be defined! 2369 #endif 2370 2371 // Mousepointer loaded ? 2372 if ( !aImplPtrTab[ePointerStyle].mhCursor ) 2373 { 2374 if ( aImplPtrTab[ePointerStyle].mnOwnId ) 2375 aImplPtrTab[ePointerStyle].mhCursor = ImplLoadSalCursor( aImplPtrTab[ePointerStyle].mnOwnId ); 2376 else 2377 aImplPtrTab[ePointerStyle].mhCursor = LoadCursor( 0, aImplPtrTab[ePointerStyle].mnSysId ); 2378 } 2379 2380 // Unterscheidet sich der Mauspointer, dann den neuen setzen 2381 if ( mhCursor != aImplPtrTab[ePointerStyle].mhCursor ) 2382 { 2383 mhCursor = aImplPtrTab[ePointerStyle].mhCursor; 2384 SetCursor( mhCursor ); 2385 } 2386 } 2387 2388 // ----------------------------------------------------------------------- 2389 2390 void WinSalFrame::CaptureMouse( sal_Bool bCapture ) 2391 { 2392 // Send this Message to the window, because CaptureMouse() only work 2393 // in the thread of the window, which has create this window 2394 int nMsg; 2395 if ( bCapture ) 2396 nMsg = SAL_MSG_CAPTUREMOUSE; 2397 else 2398 nMsg = SAL_MSG_RELEASEMOUSE; 2399 ImplSendMessage( mhWnd, nMsg, 0, 0 ); 2400 } 2401 2402 // ----------------------------------------------------------------------- 2403 2404 void WinSalFrame::SetPointerPos( long nX, long nY ) 2405 { 2406 POINT aPt; 2407 aPt.x = (int)nX; 2408 aPt.y = (int)nY; 2409 ClientToScreen( mhWnd, &aPt ); 2410 SetCursorPos( aPt.x, aPt.y ); 2411 } 2412 2413 // ----------------------------------------------------------------------- 2414 2415 void WinSalFrame::Flush() 2416 { 2417 GdiFlush(); 2418 } 2419 2420 // ----------------------------------------------------------------------- 2421 2422 void WinSalFrame::Sync() 2423 { 2424 GdiFlush(); 2425 } 2426 2427 // ----------------------------------------------------------------------- 2428 2429 static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pContext ) 2430 { 2431 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 2432 sal_Bool bIME = (pContext->mnOptions & SAL_INPUTCONTEXT_TEXT) != 0; 2433 if ( bIME ) 2434 { 2435 if ( !pFrame->mbIME ) 2436 { 2437 pFrame->mbIME = TRUE; 2438 2439 if ( pFrame->mhDefIMEContext ) 2440 { 2441 ImmAssociateContext( pFrame->mhWnd, pFrame->mhDefIMEContext ); 2442 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY ); 2443 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0; 2444 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0; 2445 pFrame->mbHandleIME = !pFrame->mbSpezIME; 2446 } 2447 } 2448 2449 // When the application can't handle IME messages, then the 2450 // System should handle the IME handling 2451 if ( !(pContext->mnOptions & SAL_INPUTCONTEXT_EXTTEXTINPUT) ) 2452 pFrame->mbHandleIME = FALSE; 2453 2454 // Set the Font for IME Handling 2455 if ( pContext->mpFont ) 2456 { 2457 HIMC hIMC = ImmGetContext( pFrame->mhWnd ); 2458 if ( hIMC ) 2459 { 2460 LOGFONTW aLogFont; 2461 HDC hDC = GetDC( pFrame->mhWnd ); 2462 // In case of vertical writing, always append a '@' to the 2463 // Windows font name, not only if such a Windows font really is 2464 // available (bTestVerticalAvail == false in the below call): 2465 // The Windows IME's candidates window seems to always use a 2466 // font that has all necessary glyphs, not necessarily the one 2467 // specified by this font name; but it seems to decide whether 2468 // to use that font's horizontal or vertical variant based on a 2469 // '@' in front of this font name. 2470 ImplGetLogFontFromFontSelect( hDC, pContext->mpFont, aLogFont, 2471 false ); 2472 ReleaseDC( pFrame->mhWnd, hDC ); 2473 ImmSetCompositionFontW( hIMC, &aLogFont ); 2474 ImmReleaseContext( pFrame->mhWnd, hIMC ); 2475 } 2476 } 2477 } 2478 else 2479 { 2480 if ( pFrame->mbIME ) 2481 { 2482 pFrame->mbIME = FALSE; 2483 pFrame->mbHandleIME = FALSE; 2484 ImmAssociateContext( pFrame->mhWnd, 0 ); 2485 } 2486 } 2487 } 2488 2489 // ----------------------------------------------------------------------- 2490 2491 void WinSalFrame::SetInputContext( SalInputContext* pContext ) 2492 { 2493 // Must be called in the main thread! 2494 ImplSendMessage( mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, (LPARAM)(void*)pContext ); 2495 } 2496 2497 // ----------------------------------------------------------------------- 2498 2499 static void ImplSalFrameEndExtTextInput( HWND hWnd, sal_uInt16 nFlags ) 2500 { 2501 HIMC hIMC = ImmGetContext( hWnd ); 2502 if ( hIMC ) 2503 { 2504 DWORD nIndex; 2505 if ( nFlags & SAL_FRAME_ENDEXTTEXTINPUT_COMPLETE ) 2506 nIndex = CPS_COMPLETE; 2507 else 2508 nIndex = CPS_CANCEL; 2509 2510 ImmNotifyIME( hIMC, NI_COMPOSITIONSTR, nIndex, 0 ); 2511 ImmReleaseContext( hWnd, hIMC ); 2512 } 2513 } 2514 2515 // ----------------------------------------------------------------------- 2516 2517 void WinSalFrame::EndExtTextInput( sal_uInt16 nFlags ) 2518 { 2519 // Must be called in the main thread! 2520 ImplSendMessage( mhWnd, SAL_MSG_ENDEXTTEXTINPUT, (WPARAM)nFlags, 0 ); 2521 } 2522 2523 // ----------------------------------------------------------------------- 2524 2525 static void ImplGetKeyNameText( LONG lParam, sal_Unicode* pBuf, 2526 UINT& rCount, UINT nMaxSize, 2527 const sal_Char* pReplace ) 2528 { 2529 DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "WinSalFrame::ImplGetKeyNameTextW(): WCHAR != sal_Unicode" ); 2530 2531 static const int nMaxKeyLen = 350; 2532 WCHAR aKeyBuf[ nMaxKeyLen ]; 2533 int nKeyLen = 0; 2534 if ( lParam ) 2535 { 2536 if ( true/*aSalShlData.mbWNT*/ ) 2537 { 2538 nKeyLen = GetKeyNameTextW( lParam, aKeyBuf, nMaxKeyLen ); 2539 DBG_ASSERT( nKeyLen <= nMaxKeyLen, "Invalid key name length!" ); 2540 if( nKeyLen > nMaxKeyLen ) 2541 nKeyLen = 0; 2542 else if( nKeyLen > 0 ) 2543 { 2544 // Capitalize just the first letter of key names 2545 CharLowerBuffW( aKeyBuf, nKeyLen ); 2546 2547 bool bUpper = true; 2548 for( WCHAR *pW=aKeyBuf, *pE=pW+nKeyLen; pW < pE; ++pW ) 2549 { 2550 if( bUpper ) 2551 CharUpperBuffW( pW, 1 ); 2552 bUpper = (*pW=='+') || (*pW=='-') || (*pW==' ') || (*pW=='.'); 2553 } 2554 } 2555 } 2556 } 2557 2558 if ( (nKeyLen > 0) || pReplace ) 2559 { 2560 if( (rCount > 0) && (rCount < nMaxSize) ) 2561 { 2562 pBuf[rCount] = '+'; 2563 rCount++; 2564 } 2565 2566 if( nKeyLen > 0 ) 2567 { 2568 if( nKeyLen + rCount > nMaxSize ) 2569 nKeyLen = nMaxSize - rCount; 2570 memcpy( pBuf+rCount, aKeyBuf, nKeyLen*sizeof( sal_Unicode ) ); 2571 rCount += nKeyLen; 2572 } 2573 else // fall back to provided default name 2574 { 2575 while( *pReplace && (rCount < nMaxSize) ) 2576 { 2577 pBuf[rCount] = *pReplace; 2578 rCount++; 2579 pReplace++; 2580 } 2581 } 2582 } 2583 else 2584 rCount = 0; 2585 } 2586 2587 // ----------------------------------------------------------------------- 2588 2589 XubString WinSalFrame::GetKeyName( sal_uInt16 nKeyCode ) 2590 { 2591 static const int nMaxKeyLen = 350; 2592 sal_Unicode aKeyBuf[ nMaxKeyLen ]; 2593 UINT nKeyBufLen = 0; 2594 UINT nSysCode = 0; 2595 2596 if ( nKeyCode & KEY_MOD1 ) 2597 { 2598 nSysCode = MapVirtualKey( VK_CONTROL, 0 ); 2599 nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25); 2600 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Ctrl" ); 2601 } 2602 2603 if ( nKeyCode & KEY_MOD2 ) 2604 { 2605 nSysCode = MapVirtualKey( VK_MENU, 0 ); 2606 nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25); 2607 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Alt" ); 2608 } 2609 2610 if ( nKeyCode & KEY_SHIFT ) 2611 { 2612 nSysCode = MapVirtualKey( VK_SHIFT, 0 ); 2613 nSysCode = (nSysCode << 16) | (((sal_uLong)1) << 25); 2614 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, "Shift" ); 2615 } 2616 2617 sal_uInt16 nCode = nKeyCode & 0x0FFF; 2618 sal_uLong nSysCode2 = 0; 2619 sal_Char* pReplace = NULL; 2620 sal_Unicode cSVCode = 0; 2621 sal_Char aFBuf[4]; 2622 nSysCode = 0; 2623 2624 if ( (nCode >= KEY_0) && (nCode <= KEY_9) ) 2625 cSVCode = '0' + (nCode - KEY_0); 2626 else if ( (nCode >= KEY_A) && (nCode <= KEY_Z) ) 2627 cSVCode = 'A' + (nCode - KEY_A); 2628 else if ( (nCode >= KEY_F1) && (nCode <= KEY_F26) ) 2629 { 2630 nSysCode = VK_F1 + (nCode - KEY_F1); 2631 aFBuf[0] = 'F'; 2632 if ( (nCode >= KEY_F1) && (nCode <= KEY_F9) ) 2633 { 2634 aFBuf[1] = sal::static_int_cast<sal_Char>('1' + (nCode - KEY_F1)); 2635 aFBuf[2] = 0; 2636 } 2637 else if ( (nCode >= KEY_F10) && (nCode <= KEY_F19) ) 2638 { 2639 aFBuf[1] = '1'; 2640 aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F10)); 2641 aFBuf[3] = 0; 2642 } 2643 else 2644 { 2645 aFBuf[1] = '2'; 2646 aFBuf[2] = sal::static_int_cast<sal_Char>('0' + (nCode - KEY_F20)); 2647 aFBuf[3] = 0; 2648 } 2649 pReplace = aFBuf; 2650 } 2651 else 2652 { 2653 switch ( nCode ) 2654 { 2655 case KEY_DOWN: 2656 nSysCode = VK_DOWN; 2657 nSysCode2 = (((sal_uLong)1) << 24); 2658 pReplace = "Down"; 2659 break; 2660 case KEY_UP: 2661 nSysCode = VK_UP; 2662 nSysCode2 = (((sal_uLong)1) << 24); 2663 pReplace = "Up"; 2664 break; 2665 case KEY_LEFT: 2666 nSysCode = VK_LEFT; 2667 nSysCode2 = (((sal_uLong)1) << 24); 2668 pReplace = "Left"; 2669 break; 2670 case KEY_RIGHT: 2671 nSysCode = VK_RIGHT; 2672 nSysCode2 = (((sal_uLong)1) << 24); 2673 pReplace = "Right"; 2674 break; 2675 case KEY_HOME: 2676 nSysCode = VK_HOME; 2677 nSysCode2 = (((sal_uLong)1) << 24); 2678 pReplace = "Home"; 2679 break; 2680 case KEY_END: 2681 nSysCode = VK_END; 2682 nSysCode2 = (((sal_uLong)1) << 24); 2683 pReplace = "End"; 2684 break; 2685 case KEY_PAGEUP: 2686 nSysCode = VK_PRIOR; 2687 nSysCode2 = (((sal_uLong)1) << 24); 2688 pReplace = "Page Up"; 2689 break; 2690 case KEY_PAGEDOWN: 2691 nSysCode = VK_NEXT; 2692 nSysCode2 = (((sal_uLong)1) << 24); 2693 pReplace = "Page Down"; 2694 break; 2695 case KEY_RETURN: 2696 nSysCode = VK_RETURN; 2697 pReplace = "Enter"; 2698 break; 2699 case KEY_ESCAPE: 2700 nSysCode = VK_ESCAPE; 2701 pReplace = "Escape"; 2702 break; 2703 case KEY_TAB: 2704 nSysCode = VK_TAB; 2705 pReplace = "Tab"; 2706 break; 2707 case KEY_BACKSPACE: 2708 nSysCode = VK_BACK; 2709 pReplace = "Backspace"; 2710 break; 2711 case KEY_SPACE: 2712 nSysCode = VK_SPACE; 2713 pReplace = "Space"; 2714 break; 2715 case KEY_INSERT: 2716 nSysCode = VK_INSERT; 2717 nSysCode2 = (((sal_uLong)1) << 24); 2718 pReplace = "Insert"; 2719 break; 2720 case KEY_DELETE: 2721 nSysCode = VK_DELETE; 2722 nSysCode2 = (((sal_uLong)1) << 24); 2723 pReplace = "Delete"; 2724 break; 2725 2726 case KEY_ADD: 2727 cSVCode = '+'; 2728 break; 2729 case KEY_SUBTRACT: 2730 cSVCode = '-'; 2731 break; 2732 case KEY_MULTIPLY: 2733 cSVCode = '*'; 2734 break; 2735 case KEY_DIVIDE: 2736 cSVCode = '/'; 2737 break; 2738 case KEY_POINT: 2739 cSVCode = '.'; 2740 break; 2741 case KEY_COMMA: 2742 cSVCode = ','; 2743 break; 2744 case KEY_LESS: 2745 cSVCode = '<'; 2746 break; 2747 case KEY_GREATER: 2748 cSVCode = '>'; 2749 break; 2750 case KEY_EQUAL: 2751 cSVCode = '='; 2752 break; 2753 } 2754 } 2755 2756 if ( nSysCode ) 2757 { 2758 nSysCode = MapVirtualKey( (UINT)nSysCode, 0 ); 2759 if ( nSysCode ) 2760 nSysCode = (nSysCode << 16) | nSysCode2; 2761 ImplGetKeyNameText( nSysCode, aKeyBuf, nKeyBufLen, nMaxKeyLen, pReplace ); 2762 } 2763 else 2764 { 2765 if ( cSVCode ) 2766 { 2767 if ( nKeyBufLen > 0 ) 2768 aKeyBuf[ nKeyBufLen++ ] = '+'; 2769 if( nKeyBufLen < nMaxKeyLen ) 2770 aKeyBuf[ nKeyBufLen++ ] = cSVCode; 2771 } 2772 } 2773 2774 if( !nKeyBufLen ) 2775 return XubString(); 2776 2777 return XubString( aKeyBuf, sal::static_int_cast< sal_uInt16 >(nKeyBufLen) ); 2778 } 2779 2780 // ----------------------------------------------------------------------- 2781 2782 XubString WinSalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode ) 2783 { 2784 return GetKeyName( nKeyCode ); 2785 } 2786 2787 // ----------------------------------------------------------------------- 2788 2789 inline Color ImplWinColorToSal( COLORREF nColor ) 2790 { 2791 return Color( GetRValue( nColor ), GetGValue( nColor ), GetBValue( nColor ) ); 2792 } 2793 2794 // ----------------------------------------------------------------------- 2795 2796 static void ImplSalUpdateStyleFontA( HDC hDC, const LOGFONTA& rLogFont, Font& rFont ) 2797 { 2798 ImplSalLogFontToFontA( hDC, rLogFont, rFont ); 2799 2800 // On Windows 9x, Windows NT we get sometimes very small sizes 2801 // (for example for the small Caption height). 2802 // So if it is MS Sans Serif, a none scalable font we use 2803 // 8 Point as the minimum control height, in all other cases 2804 // 6 Point is the smallest one 2805 if ( rFont.GetHeight() < 8 ) 2806 { 2807 if ( rtl_str_compareIgnoreAsciiCase( rLogFont.lfFaceName, "MS Sans Serif" ) == 0 ) 2808 rFont.SetHeight( 8 ); 2809 else if ( rFont.GetHeight() < 6 ) 2810 rFont.SetHeight( 6 ); 2811 } 2812 } 2813 2814 // ----------------------------------------------------------------------- 2815 2816 static void ImplSalUpdateStyleFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont ) 2817 { 2818 ImplSalLogFontToFontW( hDC, rLogFont, rFont ); 2819 2820 // On Windows 9x, Windows NT we get sometimes very small sizes 2821 // (for example for the small Caption height). 2822 // So if it is MS Sans Serif, a none scalable font we use 2823 // 8 Point as the minimum control height, in all other cases 2824 // 6 Point is the smallest one 2825 if ( rFont.GetHeight() < 8 ) 2826 { 2827 if ( rtl_ustr_compareIgnoreAsciiCase( reinterpret_cast<const sal_Unicode*>(rLogFont.lfFaceName), reinterpret_cast<const sal_Unicode*>(L"MS Sans Serif") ) == 0 ) 2828 rFont.SetHeight( 8 ); 2829 else if ( rFont.GetHeight() < 6 ) 2830 rFont.SetHeight( 6 ); 2831 } 2832 } 2833 2834 // ----------------------------------------------------------------------- 2835 2836 static long ImplA2I( const BYTE* pStr ) 2837 { 2838 long n = 0; 2839 int nSign = 1; 2840 2841 if ( *pStr == '-' ) 2842 { 2843 nSign = -1; 2844 pStr++; 2845 } 2846 2847 while( (*pStr >= 48) && (*pStr <= 57) ) 2848 { 2849 n *= 10; 2850 n += ((*pStr) - 48); 2851 pStr++; 2852 } 2853 2854 n *= nSign; 2855 2856 return n; 2857 } 2858 2859 // ----------------------------------------------------------------------- 2860 static HRESULT WINAPI backwardCompatibleDwmIsCompositionEnabled( BOOL* pOut ) 2861 { 2862 *pOut = FALSE; 2863 return S_OK; 2864 } 2865 2866 static BOOL ImplDwmIsCompositionEnabled() 2867 { 2868 SalData* pSalData = GetSalData(); 2869 if( ! pSalData->mpDwmIsCompositionEnabled ) 2870 { 2871 pSalData->maDwmLib = osl_loadAsciiModule( "Dwmapi.dll", SAL_LOADMODULE_DEFAULT ); 2872 if( pSalData->maDwmLib ) 2873 pSalData->mpDwmIsCompositionEnabled = (DwmIsCompositionEnabled_ptr)osl_getAsciiFunctionSymbol( pSalData->maDwmLib, "DwmIsCompositionEnabled" ); 2874 if( ! pSalData->mpDwmIsCompositionEnabled ) // something failed 2875 pSalData->mpDwmIsCompositionEnabled = backwardCompatibleDwmIsCompositionEnabled; 2876 } 2877 BOOL aResult = FALSE; 2878 HRESULT nError = pSalData->mpDwmIsCompositionEnabled( &aResult ); 2879 return nError == S_OK && aResult; 2880 } 2881 2882 2883 void WinSalFrame::UpdateSettings( AllSettings& rSettings ) 2884 { 2885 MouseSettings aMouseSettings = rSettings.GetMouseSettings(); 2886 aMouseSettings.SetDoubleClickTime( GetDoubleClickTime() ); 2887 aMouseSettings.SetDoubleClickWidth( GetSystemMetrics( SM_CXDOUBLECLK ) ); 2888 aMouseSettings.SetDoubleClickHeight( GetSystemMetrics( SM_CYDOUBLECLK ) ); 2889 long nDragWidth = GetSystemMetrics( SM_CXDRAG ); 2890 long nDragHeight = GetSystemMetrics( SM_CYDRAG ); 2891 if ( nDragWidth ) 2892 aMouseSettings.SetStartDragWidth( nDragWidth ); 2893 if ( nDragHeight ) 2894 aMouseSettings.SetStartDragHeight( nDragHeight ); 2895 HKEY hRegKey; 2896 if ( RegOpenKey( HKEY_CURRENT_USER, 2897 "Control Panel\\Desktop", 2898 &hRegKey ) == ERROR_SUCCESS ) 2899 { 2900 BYTE aValueBuf[10]; 2901 DWORD nValueSize = sizeof( aValueBuf ); 2902 DWORD nType; 2903 if ( RegQueryValueEx( hRegKey, "MenuShowDelay", 0, 2904 &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS ) 2905 { 2906 if ( nType == REG_SZ ) 2907 aMouseSettings.SetMenuDelay( (sal_uLong)ImplA2I( aValueBuf ) ); 2908 } 2909 2910 RegCloseKey( hRegKey ); 2911 } 2912 2913 StyleSettings aStyleSettings = rSettings.GetStyleSettings(); 2914 // TODO: once those options vanish: just set bCompBorder to TRUE 2915 // to have the system colors read 2916 aStyleSettings.SetScrollBarSize( GetSystemMetrics( SM_CXVSCROLL ) ); 2917 aStyleSettings.SetSpinSize( GetSystemMetrics( SM_CXVSCROLL ) ); 2918 aStyleSettings.SetCursorBlinkTime( GetCaretBlinkTime() ); 2919 aStyleSettings.SetFloatTitleHeight( GetSystemMetrics( SM_CYSMCAPTION ) ); 2920 aStyleSettings.SetTitleHeight( GetSystemMetrics( SM_CYCAPTION ) ); 2921 aStyleSettings.SetActiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVEBORDER ) ) ); 2922 aStyleSettings.SetDeactiveBorderColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVEBORDER ) ) ); 2923 if ( aSalShlData.mnVersion >= 410 ) 2924 { 2925 aStyleSettings.SetActiveColor2( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTACTIVECAPTION ) ) ); 2926 aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_GRADIENTINACTIVECAPTION ) ) ); 2927 } 2928 aStyleSettings.SetFaceColor( ImplWinColorToSal( GetSysColor( COLOR_3DFACE ) ) ); 2929 aStyleSettings.SetInactiveTabColor( aStyleSettings.GetFaceColor() ); 2930 aStyleSettings.SetLightColor( ImplWinColorToSal( GetSysColor( COLOR_3DHILIGHT ) ) ); 2931 aStyleSettings.SetLightBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DLIGHT ) ) ); 2932 aStyleSettings.SetShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) ); 2933 aStyleSettings.SetDarkShadowColor( ImplWinColorToSal( GetSysColor( COLOR_3DDKSHADOW ) ) ); 2934 aStyleSettings.SetWorkspaceColor( ImplWinColorToSal( GetSysColor( COLOR_APPWORKSPACE ) ) ); 2935 aStyleSettings.SetHelpColor( ImplWinColorToSal( GetSysColor( COLOR_INFOBK ) ) ); 2936 aStyleSettings.SetHelpTextColor( ImplWinColorToSal( GetSysColor( COLOR_INFOTEXT ) ) ); 2937 aStyleSettings.SetDialogColor( aStyleSettings.GetFaceColor() ); 2938 aStyleSettings.SetDialogTextColor( aStyleSettings.GetButtonTextColor() ); 2939 aStyleSettings.SetButtonTextColor( ImplWinColorToSal( GetSysColor( COLOR_BTNTEXT ) ) ); 2940 aStyleSettings.SetButtonRolloverTextColor( aStyleSettings.GetButtonTextColor() ); 2941 aStyleSettings.SetRadioCheckTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) ); 2942 aStyleSettings.SetGroupTextColor( aStyleSettings.GetRadioCheckTextColor() ); 2943 aStyleSettings.SetLabelTextColor( aStyleSettings.GetRadioCheckTextColor() ); 2944 aStyleSettings.SetInfoTextColor( aStyleSettings.GetRadioCheckTextColor() ); 2945 aStyleSettings.SetWindowColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOW ) ) ); 2946 aStyleSettings.SetActiveTabColor( aStyleSettings.GetWindowColor() ); 2947 aStyleSettings.SetWindowTextColor( ImplWinColorToSal( GetSysColor( COLOR_WINDOWTEXT ) ) ); 2948 aStyleSettings.SetFieldColor( aStyleSettings.GetWindowColor() ); 2949 aStyleSettings.SetFieldTextColor( aStyleSettings.GetWindowTextColor() ); 2950 aStyleSettings.SetFieldRolloverTextColor( aStyleSettings.GetFieldTextColor() ); 2951 aStyleSettings.SetHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHT ) ) ); 2952 aStyleSettings.SetHighlightTextColor( ImplWinColorToSal( GetSysColor( COLOR_HIGHLIGHTTEXT ) ) ); 2953 aStyleSettings.SetMenuHighlightColor( aStyleSettings.GetHighlightColor() ); 2954 aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetHighlightTextColor() ); 2955 2956 ImplSVData* pSVData = ImplGetSVData(); 2957 pSVData->maNWFData.mnMenuFormatExtraBorder = 0; 2958 pSVData->maNWFData.maMenuBarHighlightTextColor = Color( COL_TRANSPARENT ); 2959 GetSalData()->mbThemeMenuSupport = FALSE; 2960 aStyleSettings.SetMenuColor( ImplWinColorToSal( GetSysColor( COLOR_MENU ) ) ); 2961 aStyleSettings.SetMenuBarColor( aStyleSettings.GetMenuColor() ); 2962 aStyleSettings.SetMenuBorderColor( aStyleSettings.GetLightBorderColor() ); // overriden below for flat menus 2963 aStyleSettings.SetUseFlatBorders( FALSE ); 2964 aStyleSettings.SetUseFlatMenues( FALSE ); 2965 aStyleSettings.SetMenuTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) ); 2966 aStyleSettings.SetMenuBarTextColor( ImplWinColorToSal( GetSysColor( COLOR_MENUTEXT ) ) ); 2967 aStyleSettings.SetActiveColor( ImplWinColorToSal( GetSysColor( COLOR_ACTIVECAPTION ) ) ); 2968 aStyleSettings.SetActiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_CAPTIONTEXT ) ) ); 2969 aStyleSettings.SetDeactiveColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTION ) ) ); 2970 aStyleSettings.SetDeactiveTextColor( ImplWinColorToSal( GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ) ); 2971 if ( aSalShlData.mbWXP ) 2972 { 2973 // only xp supports a different menu bar color 2974 long bFlatMenues = 0; 2975 SystemParametersInfo( SPI_GETFLATMENU, 0, &bFlatMenues, 0); 2976 if( bFlatMenues ) 2977 { 2978 aStyleSettings.SetUseFlatMenues( TRUE ); 2979 aStyleSettings.SetMenuBarColor( ImplWinColorToSal( GetSysColor( COLOR_MENUBAR ) ) ); 2980 aStyleSettings.SetMenuHighlightColor( ImplWinColorToSal( GetSysColor( COLOR_MENUHILIGHT ) ) ); 2981 aStyleSettings.SetMenuBorderColor( ImplWinColorToSal( GetSysColor( COLOR_3DSHADOW ) ) ); 2982 2983 // flat borders for our controls etc. as well in this mode (i.e. no 3D borders) 2984 // this is not active in the classic style appearance 2985 aStyleSettings.SetUseFlatBorders( TRUE ); 2986 } 2987 } 2988 // check if vista or newer runs 2989 // in Aero theme (and similar ?) the menu text color does not change 2990 // for selected items; also on WinXP and earlier menus are not themed 2991 if( aSalShlData.maVersionInfo.dwMajorVersion >= 6 && 2992 ImplDwmIsCompositionEnabled() 2993 ) 2994 { 2995 // in Aero menuitem highlight text is drawn in the same color as normal 2996 aStyleSettings.SetMenuHighlightTextColor( aStyleSettings.GetMenuTextColor() ); 2997 pSVData->maNWFData.mnMenuFormatExtraBorder = 2; 2998 pSVData->maNWFData.maMenuBarHighlightTextColor = aStyleSettings.GetMenuTextColor(); 2999 GetSalData()->mbThemeMenuSupport = TRUE; 3000 } 3001 // Bei hellgrau geben wir die Farbe vor, damit es besser aussieht 3002 if ( aStyleSettings.GetFaceColor() == COL_LIGHTGRAY ) 3003 aStyleSettings.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) ); 3004 else 3005 { 3006 // Checked-Color berechnen 3007 Color aColor1 = aStyleSettings.GetFaceColor(); 3008 Color aColor2 = aStyleSettings.GetLightColor(); 3009 BYTE nRed = (BYTE)(((sal_uInt16)aColor1.GetRed() + (sal_uInt16)aColor2.GetRed())/2); 3010 BYTE nGreen = (BYTE)(((sal_uInt16)aColor1.GetGreen() + (sal_uInt16)aColor2.GetGreen())/2); 3011 BYTE nBlue = (BYTE)(((sal_uInt16)aColor1.GetBlue() + (sal_uInt16)aColor2.GetBlue())/2); 3012 aStyleSettings.SetCheckedColor( Color( nRed, nGreen, nBlue ) ); 3013 } 3014 3015 // caret width 3016 DWORD nCaretWidth = 2; 3017 if( SystemParametersInfo( SPI_GETCARETWIDTH, 0, &nCaretWidth, 0 ) ) 3018 aStyleSettings.SetCursorSize( nCaretWidth ); 3019 3020 // High contrast 3021 HIGHCONTRAST hc; 3022 hc.cbSize = sizeof( HIGHCONTRAST ); 3023 if( SystemParametersInfo( SPI_GETHIGHCONTRAST, hc.cbSize, &hc, 0) && (hc.dwFlags & HCF_HIGHCONTRASTON) ) 3024 aStyleSettings.SetHighContrastMode( 1 ); 3025 else 3026 aStyleSettings.SetHighContrastMode( 0 ); 3027 3028 3029 // Query Fonts 3030 Font aMenuFont = aStyleSettings.GetMenuFont(); 3031 Font aTitleFont = aStyleSettings.GetTitleFont(); 3032 Font aFloatTitleFont = aStyleSettings.GetFloatTitleFont(); 3033 Font aHelpFont = aStyleSettings.GetHelpFont(); 3034 Font aAppFont = aStyleSettings.GetAppFont(); 3035 Font aIconFont = aStyleSettings.GetIconFont(); 3036 HDC hDC = GetDC( 0 ); 3037 if( true/*aSalShlData.mbWNT*/ ) 3038 { 3039 NONCLIENTMETRICSW aNonClientMetrics; 3040 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics ); 3041 if ( SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) ) 3042 { 3043 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMenuFont, aMenuFont ); 3044 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfCaptionFont, aTitleFont ); 3045 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfSmCaptionFont, aFloatTitleFont ); 3046 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfStatusFont, aHelpFont ); 3047 ImplSalUpdateStyleFontW( hDC, aNonClientMetrics.lfMessageFont, aAppFont ); 3048 3049 LOGFONTW aLogFont; 3050 if ( SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &aLogFont, 0 ) ) 3051 ImplSalUpdateStyleFontW( hDC, aLogFont, aIconFont ); 3052 } 3053 } 3054 3055 // get screen font resolution to calculate toolbox item size 3056 long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY ); 3057 3058 ReleaseDC( 0, hDC ); 3059 3060 long nHeightPx = aMenuFont.GetHeight() * nDPIY / 72; 3061 aStyleSettings.SetToolbarIconSize( (((nHeightPx-1)*2) >= 28) ? STYLE_TOOLBAR_ICONSIZE_LARGE : STYLE_TOOLBAR_ICONSIZE_SMALL ); 3062 3063 aStyleSettings.SetMenuFont( aMenuFont ); 3064 aStyleSettings.SetTitleFont( aTitleFont ); 3065 aStyleSettings.SetFloatTitleFont( aFloatTitleFont ); 3066 aStyleSettings.SetHelpFont( aHelpFont ); 3067 aStyleSettings.SetIconFont( aIconFont ); 3068 // We prefer Arial in the Russian version, because MS Sans Serif 3069 // is to wide for the dialogs 3070 if ( rSettings.GetLanguage() == LANGUAGE_RUSSIAN ) 3071 { 3072 XubString aFontName = aAppFont.GetName(); 3073 XubString aFirstName = aFontName.GetToken( 0, ';' ); 3074 if ( aFirstName.EqualsIgnoreCaseAscii( "MS Sans Serif" ) ) 3075 { 3076 aFontName.InsertAscii( "Arial;", 0 ); 3077 aAppFont.SetName( aFontName ); 3078 } 3079 } 3080 aStyleSettings.SetAppFont( aAppFont ); 3081 aStyleSettings.SetGroupFont( aAppFont ); 3082 aStyleSettings.SetLabelFont( aAppFont ); 3083 aStyleSettings.SetRadioCheckFont( aAppFont ); 3084 aStyleSettings.SetPushButtonFont( aAppFont ); 3085 aStyleSettings.SetFieldFont( aAppFont ); 3086 if ( aAppFont.GetWeight() > WEIGHT_NORMAL ) 3087 aAppFont.SetWeight( WEIGHT_NORMAL ); 3088 aStyleSettings.SetInfoFont( aAppFont ); 3089 aStyleSettings.SetToolFont( aAppFont ); 3090 3091 BOOL bDragFull; 3092 if ( SystemParametersInfo( SPI_GETDRAGFULLWINDOWS, 0, &bDragFull, 0 ) ) 3093 { 3094 sal_uLong nDragFullOptions = aStyleSettings.GetDragFullOptions(); 3095 if ( bDragFull ) 3096 nDragFullOptions |= DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT; 3097 else 3098 nDragFullOptions &= ~(DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT); 3099 aStyleSettings.SetDragFullOptions( nDragFullOptions ); 3100 } 3101 3102 aStyleSettings.SetIconHorzSpace( GetSystemMetrics( SM_CXICONSPACING ) ); 3103 aStyleSettings.SetIconVertSpace( GetSystemMetrics( SM_CYICONSPACING ) ); 3104 if ( RegOpenKey( HKEY_CURRENT_USER, 3105 "Control Panel\\International\\Calendars\\TwoDigitYearMax", 3106 &hRegKey ) == ERROR_SUCCESS ) 3107 { 3108 BYTE aValueBuf[10]; 3109 DWORD nValue; 3110 DWORD nValueSize = sizeof( aValueBuf ); 3111 DWORD nType; 3112 if ( RegQueryValueEx( hRegKey, "1", 0, 3113 &nType, aValueBuf, &nValueSize ) == ERROR_SUCCESS ) 3114 { 3115 if ( nType == REG_SZ ) 3116 { 3117 nValue = (sal_uLong)ImplA2I( aValueBuf ); 3118 if ( (nValue > 1000) && (nValue < 10000) ) 3119 { 3120 MiscSettings aMiscSettings = rSettings.GetMiscSettings(); 3121 utl::MiscCfg().SetYear2000( (sal_Int32)(nValue-99) ); 3122 rSettings.SetMiscSettings( aMiscSettings ); 3123 } 3124 } 3125 } 3126 3127 RegCloseKey( hRegKey ); 3128 } 3129 3130 rSettings.SetMouseSettings( aMouseSettings ); 3131 rSettings.SetStyleSettings( aStyleSettings ); 3132 } 3133 3134 // ----------------------------------------------------------------------- 3135 3136 SalBitmap* WinSalFrame::SnapShot() 3137 { 3138 WinSalBitmap* pSalBitmap = NULL; 3139 3140 RECT aRect; 3141 GetWindowRect( mhWnd, &aRect ); 3142 3143 int nDX = aRect.right-aRect.left; 3144 int nDY = aRect.bottom-aRect.top; 3145 HDC hDC = GetWindowDC( mhWnd ); 3146 HBITMAP hBmpBitmap = CreateCompatibleBitmap( hDC, nDX, nDY ); 3147 HDC hBmpDC = ImplGetCachedDC( CACHED_HDC_1, hBmpBitmap ); 3148 sal_Bool bRet; 3149 3150 bRet = BitBlt( hBmpDC, 0, 0, nDX, nDY, hDC, 0, 0, SRCCOPY ) ? TRUE : FALSE; 3151 ImplReleaseCachedDC( CACHED_HDC_1 ); 3152 3153 if ( bRet ) 3154 { 3155 pSalBitmap = new WinSalBitmap; 3156 3157 if ( !pSalBitmap->Create( hBmpBitmap, FALSE, FALSE ) ) 3158 { 3159 delete pSalBitmap; 3160 pSalBitmap = NULL; 3161 } 3162 } 3163 3164 return pSalBitmap; 3165 } 3166 3167 // ----------------------------------------------------------------------- 3168 3169 const SystemEnvData* WinSalFrame::GetSystemData() const 3170 { 3171 return &maSysData; 3172 } 3173 3174 // ----------------------------------------------------------------------- 3175 3176 void WinSalFrame::Beep( SoundType eSoundType ) 3177 { 3178 static UINT aImplSoundTab[5] = 3179 { 3180 0, // SOUND_DEFAULT 3181 MB_ICONASTERISK, // SOUND_INFO 3182 MB_ICONEXCLAMATION, // SOUND_WARNING 3183 MB_ICONHAND, // SOUND_ERROR 3184 MB_ICONQUESTION // SOUND_QUERY 3185 }; 3186 3187 if( eSoundType != SOUND_DISABLE ) // don't beep on disable 3188 MessageBeep( aImplSoundTab[eSoundType] ); 3189 } 3190 3191 // ----------------------------------------------------------------------- 3192 3193 SalFrame::SalPointerState WinSalFrame::GetPointerState() 3194 { 3195 SalPointerState aState; 3196 aState.mnState = 0; 3197 3198 if ( GetKeyState( VK_LBUTTON ) & 0x8000 ) 3199 aState.mnState |= MOUSE_LEFT; 3200 if ( GetKeyState( VK_MBUTTON ) & 0x8000 ) 3201 aState.mnState |= MOUSE_MIDDLE; 3202 if ( GetKeyState( VK_RBUTTON ) & 0x8000 ) 3203 aState.mnState |= MOUSE_RIGHT; 3204 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 3205 aState.mnState |= KEY_SHIFT; 3206 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 3207 aState.mnState |= KEY_MOD1; 3208 if ( GetKeyState( VK_MENU ) & 0x8000 ) 3209 aState.mnState |= KEY_MOD2; 3210 3211 POINT pt; 3212 GetCursorPos( &pt ); 3213 3214 aState.maPos = Point( pt.x - maGeometry.nX, pt.y - maGeometry.nY ); 3215 return aState; 3216 } 3217 3218 // ----------------------------------------------------------------------- 3219 3220 void WinSalFrame::SetBackgroundBitmap( SalBitmap* ) 3221 { 3222 } 3223 3224 // ----------------------------------------------------------------------- 3225 3226 void WinSalFrame::ResetClipRegion() 3227 { 3228 SetWindowRgn( mhWnd, 0, TRUE ); 3229 } 3230 3231 // ----------------------------------------------------------------------- 3232 3233 void WinSalFrame::BeginSetClipRegion( sal_uLong nRects ) 3234 { 3235 if( mpClipRgnData ) 3236 delete [] (BYTE*)mpClipRgnData; 3237 sal_uLong nRectBufSize = sizeof(RECT)*nRects; 3238 mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize]; 3239 mpClipRgnData->rdh.dwSize = sizeof( RGNDATAHEADER ); 3240 mpClipRgnData->rdh.iType = RDH_RECTANGLES; 3241 mpClipRgnData->rdh.nCount = nRects; 3242 mpClipRgnData->rdh.nRgnSize = nRectBufSize; 3243 SetRectEmpty( &(mpClipRgnData->rdh.rcBound) ); 3244 mpNextClipRect = (RECT*)(&(mpClipRgnData->Buffer)); 3245 mbFirstClipRect = TRUE; 3246 } 3247 3248 // ----------------------------------------------------------------------- 3249 3250 void WinSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) 3251 { 3252 if( ! mpClipRgnData ) 3253 return; 3254 3255 RECT* pRect = mpNextClipRect; 3256 RECT* pBoundRect = &(mpClipRgnData->rdh.rcBound); 3257 long nRight = nX + nWidth; 3258 long nBottom = nY + nHeight; 3259 3260 if ( mbFirstClipRect ) 3261 { 3262 pBoundRect->left = nX; 3263 pBoundRect->top = nY; 3264 pBoundRect->right = nRight; 3265 pBoundRect->bottom = nBottom; 3266 mbFirstClipRect = FALSE; 3267 } 3268 else 3269 { 3270 if ( nX < pBoundRect->left ) 3271 pBoundRect->left = (int)nX; 3272 3273 if ( nY < pBoundRect->top ) 3274 pBoundRect->top = (int)nY; 3275 3276 if ( nRight > pBoundRect->right ) 3277 pBoundRect->right = (int)nRight; 3278 3279 if ( nBottom > pBoundRect->bottom ) 3280 pBoundRect->bottom = (int)nBottom; 3281 } 3282 3283 pRect->left = (int)nX; 3284 pRect->top = (int)nY; 3285 pRect->right = (int)nRight; 3286 pRect->bottom = (int)nBottom; 3287 if( (mpNextClipRect - (RECT*)(&mpClipRgnData->Buffer)) < (int)mpClipRgnData->rdh.nCount ) 3288 mpNextClipRect++; 3289 } 3290 3291 // ----------------------------------------------------------------------- 3292 3293 void WinSalFrame::EndSetClipRegion() 3294 { 3295 if( ! mpClipRgnData ) 3296 return; 3297 3298 HRGN hRegion; 3299 3300 // create region from accumulated rectangles 3301 if ( mpClipRgnData->rdh.nCount == 1 ) 3302 { 3303 RECT* pRect = &(mpClipRgnData->rdh.rcBound); 3304 hRegion = CreateRectRgn( pRect->left, pRect->top, 3305 pRect->right, pRect->bottom ); 3306 } 3307 else 3308 { 3309 sal_uLong nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER); 3310 hRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData ); 3311 } 3312 delete [] (BYTE*)mpClipRgnData; 3313 mpClipRgnData = NULL; 3314 3315 DBG_ASSERT( hRegion, "WinSalFrame::EndSetClipRegion() - Can't create ClipRegion" ); 3316 if( hRegion ) 3317 { 3318 RECT aWindowRect; 3319 GetWindowRect( mhWnd, &aWindowRect ); 3320 POINT aPt; 3321 aPt.x=0; 3322 aPt.y=0; 3323 ClientToScreen( mhWnd, &aPt ); 3324 OffsetRgn( hRegion, aPt.x - aWindowRect.left, aPt.y - aWindowRect.top ); 3325 3326 if( SetWindowRgn( mhWnd, hRegion, TRUE ) == 0 ) 3327 DeleteObject( hRegion ); 3328 } 3329 } 3330 3331 // ----------------------------------------------------------------------- 3332 3333 static long ImplHandleMouseMsg( HWND hWnd, UINT nMsg, 3334 WPARAM wParam, LPARAM lParam ) 3335 { 3336 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3337 if ( !pFrame ) 3338 return 0; 3339 3340 if( nMsg == WM_LBUTTONDOWN || nMsg == WM_MBUTTONDOWN || nMsg == WM_RBUTTONDOWN ) 3341 { 3342 // #103168# post again if async focus has not arrived yet 3343 // hopefully we will not receive the corresponding button up before this 3344 // button down arrives again 3345 Window *pWin = pFrame->GetWindow(); 3346 if( pWin && pWin->ImplGetWindowImpl()->mpFrameData->mnFocusId ) 3347 { 3348 ImplPostMessage( hWnd, nMsg, wParam, lParam ); 3349 return 1; 3350 } 3351 } 3352 SalMouseEvent aMouseEvt; 3353 long nRet; 3354 sal_uInt16 nEvent = 0; 3355 sal_Bool bCall = TRUE; 3356 3357 aMouseEvt.mnX = (short)LOWORD( lParam ); 3358 aMouseEvt.mnY = (short)HIWORD( lParam ); 3359 aMouseEvt.mnCode = 0; 3360 aMouseEvt.mnTime = GetMessageTime(); 3361 3362 // Wegen (Logitech-)MouseTreiber ueber GetKeyState() gehen, die auf 3363 // mittlerer Maustaste Doppelklick simulieren und den KeyStatus nicht 3364 // beruecksichtigen 3365 3366 if ( GetKeyState( VK_LBUTTON ) & 0x8000 ) 3367 aMouseEvt.mnCode |= MOUSE_LEFT; 3368 if ( GetKeyState( VK_MBUTTON ) & 0x8000 ) 3369 aMouseEvt.mnCode |= MOUSE_MIDDLE; 3370 if ( GetKeyState( VK_RBUTTON ) & 0x8000 ) 3371 aMouseEvt.mnCode |= MOUSE_RIGHT; 3372 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 3373 aMouseEvt.mnCode |= KEY_SHIFT; 3374 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 3375 aMouseEvt.mnCode |= KEY_MOD1; 3376 if ( GetKeyState( VK_MENU ) & 0x8000 ) 3377 aMouseEvt.mnCode |= KEY_MOD2; 3378 3379 switch ( nMsg ) 3380 { 3381 case WM_MOUSEMOVE: 3382 { 3383 // Da bei Druecken von Modifier-Tasten die MouseEvents 3384 // nicht zusammengefast werden (da diese durch KeyEvents 3385 // unterbrochen werden), machen wir dieses hier selber 3386 if ( aMouseEvt.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2) ) 3387 { 3388 MSG aTempMsg; 3389 if ( ImplPeekMessage( &aTempMsg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE | PM_NOYIELD ) ) 3390 { 3391 if ( (aTempMsg.message == WM_MOUSEMOVE) && 3392 (aTempMsg.wParam == wParam) ) 3393 return 1; 3394 } 3395 } 3396 3397 SalData* pSalData = GetSalData(); 3398 // Test for MouseLeave 3399 if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) ) 3400 ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() ); 3401 3402 pSalData->mhWantLeaveMsg = hWnd; 3403 // Start MouseLeave-Timer 3404 if ( !pSalData->mpMouseLeaveTimer ) 3405 { 3406 pSalData->mpMouseLeaveTimer = new AutoTimer; 3407 pSalData->mpMouseLeaveTimer->SetTimeout( SAL_MOUSELEAVE_TIMEOUT ); 3408 pSalData->mpMouseLeaveTimer->Start(); 3409 // We don't need to set a timeout handler, because we test 3410 // for mouseleave in the timeout callback 3411 } 3412 aMouseEvt.mnButton = 0; 3413 nEvent = SALEVENT_MOUSEMOVE; 3414 } 3415 break; 3416 3417 case WM_NCMOUSEMOVE: 3418 case SAL_MSG_MOUSELEAVE: 3419 { 3420 SalData* pSalData = GetSalData(); 3421 if ( pSalData->mhWantLeaveMsg == hWnd ) 3422 { 3423 pSalData->mhWantLeaveMsg = 0; 3424 if ( pSalData->mpMouseLeaveTimer ) 3425 { 3426 delete pSalData->mpMouseLeaveTimer; 3427 pSalData->mpMouseLeaveTimer = NULL; 3428 } 3429 // Mouse-Coordinates are relative to the screen 3430 POINT aPt; 3431 aPt.x = (short)LOWORD( lParam ); 3432 aPt.y = (short)HIWORD( lParam ); 3433 ScreenToClient( hWnd, &aPt ); 3434 aMouseEvt.mnX = aPt.x; 3435 aMouseEvt.mnY = aPt.y; 3436 aMouseEvt.mnButton = 0; 3437 nEvent = SALEVENT_MOUSELEAVE; 3438 } 3439 else 3440 bCall = FALSE; 3441 } 3442 break; 3443 3444 case WM_LBUTTONDOWN: 3445 aMouseEvt.mnButton = MOUSE_LEFT; 3446 nEvent = SALEVENT_MOUSEBUTTONDOWN; 3447 break; 3448 3449 case WM_MBUTTONDOWN: 3450 aMouseEvt.mnButton = MOUSE_MIDDLE; 3451 nEvent = SALEVENT_MOUSEBUTTONDOWN; 3452 break; 3453 3454 case WM_RBUTTONDOWN: 3455 aMouseEvt.mnButton = MOUSE_RIGHT; 3456 nEvent = SALEVENT_MOUSEBUTTONDOWN; 3457 break; 3458 3459 case WM_LBUTTONUP: 3460 aMouseEvt.mnButton = MOUSE_LEFT; 3461 nEvent = SALEVENT_MOUSEBUTTONUP; 3462 break; 3463 3464 case WM_MBUTTONUP: 3465 aMouseEvt.mnButton = MOUSE_MIDDLE; 3466 nEvent = SALEVENT_MOUSEBUTTONUP; 3467 break; 3468 3469 case WM_RBUTTONUP: 3470 aMouseEvt.mnButton = MOUSE_RIGHT; 3471 nEvent = SALEVENT_MOUSEBUTTONUP; 3472 break; 3473 } 3474 3475 // check if this window was destroyed - this might happen if we are the help window 3476 // and sent a mouse leave message to the application which killed the help window, i.e. ourself 3477 if( !IsWindow( hWnd ) ) 3478 return 0; 3479 3480 if ( bCall ) 3481 { 3482 if ( nEvent == SALEVENT_MOUSEBUTTONDOWN ) 3483 UpdateWindow( hWnd ); 3484 3485 // --- RTL --- (mirror mouse pos) 3486 if( Application::GetSettings().GetLayoutRTL() ) 3487 aMouseEvt.mnX = pFrame->maGeometry.nWidth-1-aMouseEvt.mnX; 3488 3489 nRet = pFrame->CallCallback( nEvent, &aMouseEvt ); 3490 if ( nMsg == WM_MOUSEMOVE ) 3491 SetCursor( pFrame->mhCursor ); 3492 } 3493 else 3494 nRet = 0; 3495 3496 return nRet; 3497 } 3498 3499 // ----------------------------------------------------------------------- 3500 3501 static long ImplHandleMouseActivateMsg( HWND hWnd ) 3502 { 3503 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3504 if ( !pFrame ) 3505 return 0; 3506 3507 if ( pFrame->mbFloatWin ) 3508 return TRUE; 3509 3510 SalMouseActivateEvent aMouseActivateEvt; 3511 POINT aPt; 3512 GetCursorPos( &aPt ); 3513 ScreenToClient( hWnd, &aPt ); 3514 aMouseActivateEvt.mnX = aPt.x; 3515 aMouseActivateEvt.mnY = aPt.y; 3516 return pFrame->CallCallback( SALEVENT_MOUSEACTIVATE, &aMouseActivateEvt ); 3517 } 3518 3519 // ----------------------------------------------------------------------- 3520 3521 static long ImplHandleWheelMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) 3522 { 3523 DBG_ASSERT( nMsg == WM_MOUSEWHEEL || 3524 nMsg == WM_MOUSEHWHEEL, 3525 "ImplHandleWheelMsg() called with no wheel mouse event" ); 3526 3527 ImplSalYieldMutexAcquireWithWait(); 3528 3529 long nRet = 0; 3530 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3531 if ( pFrame ) 3532 { 3533 WORD nWinModCode = LOWORD( wParam ); 3534 POINT aWinPt; 3535 aWinPt.x = (short)LOWORD( lParam ); 3536 aWinPt.y = (short)HIWORD( lParam ); 3537 ScreenToClient( hWnd, &aWinPt ); 3538 3539 SalWheelMouseEvent aWheelEvt; 3540 aWheelEvt.mnTime = GetMessageTime(); 3541 aWheelEvt.mnX = aWinPt.x; 3542 aWheelEvt.mnY = aWinPt.y; 3543 aWheelEvt.mnCode = 0; 3544 aWheelEvt.mnDelta = (short)HIWORD( wParam ); 3545 aWheelEvt.mnNotchDelta = aWheelEvt.mnDelta/WHEEL_DELTA; 3546 if( aWheelEvt.mnNotchDelta == 0 ) 3547 { 3548 if( aWheelEvt.mnDelta > 0 ) 3549 aWheelEvt.mnNotchDelta = 1; 3550 else if( aWheelEvt.mnDelta < 0 ) 3551 aWheelEvt.mnNotchDelta = -1; 3552 } 3553 3554 if( nMsg == WM_MOUSEWHEEL ) 3555 { 3556 if ( aSalShlData.mnWheelScrollLines == WHEEL_PAGESCROLL ) 3557 aWheelEvt.mnScrollLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; 3558 else 3559 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollLines; 3560 aWheelEvt.mbHorz = FALSE; 3561 } 3562 else 3563 { 3564 aWheelEvt.mnScrollLines = aSalShlData.mnWheelScrollChars; 3565 aWheelEvt.mbHorz = TRUE; 3566 // BZ 95390 - seems horiz scrolling has swapped direction 3567 aWheelEvt.mnDelta *= -1; 3568 aWheelEvt.mnNotchDelta *= -1; 3569 } 3570 3571 if ( nWinModCode & MK_SHIFT ) 3572 aWheelEvt.mnCode |= KEY_SHIFT; 3573 if ( nWinModCode & MK_CONTROL ) 3574 aWheelEvt.mnCode |= KEY_MOD1; 3575 if ( GetKeyState( VK_MENU ) & 0x8000 ) 3576 aWheelEvt.mnCode |= KEY_MOD2; 3577 3578 // --- RTL --- (mirror mouse pos) 3579 if( Application::GetSettings().GetLayoutRTL() ) 3580 aWheelEvt.mnX = pFrame->maGeometry.nWidth-1-aWheelEvt.mnX; 3581 3582 nRet = pFrame->CallCallback( SALEVENT_WHEELMOUSE, &aWheelEvt ); 3583 } 3584 3585 ImplSalYieldMutexRelease(); 3586 3587 return nRet; 3588 } 3589 3590 // ----------------------------------------------------------------------- 3591 3592 static sal_uInt16 ImplSalGetKeyCode( WPARAM wParam ) 3593 { 3594 sal_uInt16 nKeyCode; 3595 3596 // convert KeyCode 3597 if ( wParam < KEY_TAB_SIZE ) 3598 nKeyCode = aImplTranslateKeyTab[wParam]; 3599 else 3600 { 3601 SalData* pSalData = GetSalData(); 3602 std::map< UINT, sal_uInt16 >::const_iterator it = pSalData->maVKMap.find( (UINT)wParam ); 3603 if( it != pSalData->maVKMap.end() ) 3604 nKeyCode = it->second; 3605 else 3606 nKeyCode = 0; 3607 } 3608 3609 return nKeyCode; 3610 } 3611 3612 // ----------------------------------------------------------------------- 3613 3614 static UINT ImplStrToNum( const sal_Char* pStr ) 3615 { 3616 sal_uInt16 n = 0; 3617 3618 // Solange es sich um eine Ziffer handelt, String umwandeln 3619 while( (*pStr >= 48) && (*pStr <= 57) ) 3620 { 3621 n *= 10; 3622 n += ((*pStr) - 48); 3623 pStr++; 3624 } 3625 3626 return n; 3627 } 3628 3629 // ----------------------------------------------------------------------- 3630 3631 static void ImplUpdateInputLang( WinSalFrame* pFrame ) 3632 { 3633 sal_Bool bLanguageChange = FALSE; 3634 UINT nLang = LOWORD( GetKeyboardLayout( 0 ) ); 3635 if ( nLang && nLang != pFrame->mnInputLang ) 3636 { 3637 // keep input lang up-to-date 3638 pFrame->mnInputLang = nLang; 3639 bLanguageChange = TRUE; 3640 } 3641 3642 // If we are on Windows NT we use Unicode FrameProcs and so we 3643 // get Unicode charcodes directly from Windows 3644 // no need to set up a code page 3645 return; 3646 } 3647 3648 3649 static sal_Unicode ImplGetCharCode( WinSalFrame* pFrame, WPARAM nCharCode ) 3650 { 3651 ImplUpdateInputLang( pFrame ); 3652 3653 // If we are on Windows NT we use Unicode FrameProcs and so we 3654 // get Unicode charcodes directly from Windows 3655 return (sal_Unicode)nCharCode; 3656 } 3657 3658 // ----------------------------------------------------------------------- 3659 3660 LanguageType WinSalFrame::GetInputLanguage() 3661 { 3662 if( !mnInputLang ) 3663 ImplUpdateInputLang( this ); 3664 3665 if( !mnInputLang ) 3666 return LANGUAGE_DONTKNOW; 3667 else 3668 return (LanguageType) mnInputLang; 3669 } 3670 3671 // ----------------------------------------------------------------------- 3672 3673 sal_Bool WinSalFrame::MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, KeyCode& rKeyCode ) 3674 { 3675 sal_Bool bRet = FALSE; 3676 HKL hkl = 0; 3677 3678 // just use the passed language identifier, do not try to load additional keyboard support 3679 hkl = (HKL) aLangType; 3680 3681 if( hkl ) 3682 { 3683 SHORT scan = VkKeyScanExW( aUnicode, hkl ); 3684 if( LOWORD(scan) == 0xFFFF ) 3685 // keyboard not loaded or key cannot be mapped 3686 bRet = FALSE; 3687 else 3688 { 3689 BYTE vkeycode = LOBYTE(scan); 3690 BYTE shiftstate = HIBYTE(scan); 3691 3692 // Last argument is set to FALSE, because there's no decision made 3693 // yet which key should be assigned to MOD3 modifier on Windows. 3694 // Windows key - user's can be confused, because it should display 3695 // Windows menu (applies to both left/right key) 3696 // Menu key - this key is used to display context menu 3697 // AltGr key - probably it has no sense 3698 rKeyCode = KeyCode( ImplSalGetKeyCode( vkeycode ), 3699 (shiftstate & 0x01) ? TRUE : FALSE, // shift 3700 (shiftstate & 0x02) ? TRUE : FALSE, // ctrl 3701 (shiftstate & 0x04) ? TRUE : FALSE, // alt 3702 FALSE ); 3703 bRet = TRUE; 3704 } 3705 } 3706 3707 return bRet; 3708 } 3709 3710 // ----------------------------------------------------------------------- 3711 3712 static long ImplHandleKeyMsg( HWND hWnd, UINT nMsg, 3713 WPARAM wParam, LPARAM lParam, LRESULT& rResult ) 3714 { 3715 static sal_Bool bIgnoreCharMsg = FALSE; 3716 static WPARAM nDeadChar = 0; 3717 static WPARAM nLastVKChar = 0; 3718 static sal_uInt16 nLastChar = 0; 3719 static sal_uInt16 nLastModKeyCode = 0; 3720 static bool bWaitForModKeyRelease = false; 3721 sal_uInt16 nRepeat = LOWORD( lParam )-1; 3722 sal_uInt16 nModCode = 0; 3723 3724 // Key wurde evtl. durch SysChild an uns weitergeleitet und 3725 // darf somit dann nicht doppelt verarbeitet werden 3726 GetSalData()->mnSalObjWantKeyEvt = 0; 3727 3728 if ( nMsg == WM_DEADCHAR ) 3729 { 3730 nDeadChar = wParam; 3731 return 0; 3732 } 3733 3734 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 3735 if ( !pFrame ) 3736 return 0; 3737 3738 // Wir restaurieren den Background-Modus bei jeder Texteingabe, 3739 // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen 3740 if ( pFrame->mpGraphics && 3741 pFrame->mpGraphics->getHDC() ) 3742 SetBkMode( pFrame->mpGraphics->getHDC(), TRANSPARENT ); 3743 3744 // determine modifiers 3745 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 3746 nModCode |= KEY_SHIFT; 3747 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 3748 nModCode |= KEY_MOD1; 3749 if ( GetKeyState( VK_MENU ) & 0x8000 ) 3750 nModCode |= KEY_MOD2; 3751 3752 if ( (nMsg == WM_CHAR) || (nMsg == WM_SYSCHAR) ) 3753 { 3754 nDeadChar = 0; 3755 3756 if ( bIgnoreCharMsg ) 3757 { 3758 bIgnoreCharMsg = FALSE; 3759 // #101635# if zero is returned here for WM_SYSCHAR (ALT+<key>) Windows will beep 3760 // becaus this 'hotkey' was not processed -> better return 1 3761 // except for Alt-SPACE which should always open the sysmenu (#104616#) 3762 3763 // also return zero if a system menubar is available that might process this hotkey 3764 // this also applies to the OLE inplace embedding where we are a child window 3765 if( (GetWindowStyle( hWnd ) & WS_CHILD) || GetMenu( hWnd ) || (wParam == 0x20) ) 3766 return 0; 3767 else 3768 return 1; 3769 } 3770 3771 // Backspace ignorieren wir als eigenstaendige Taste, 3772 // damit wir keine Probleme in Kombination mit einem 3773 // DeadKey bekommen 3774 if ( wParam == 0x08 ) // BACKSPACE 3775 return 0; 3776 3777 // Hier kommen nur "freifliegende" WM_CHAR Message an, die durch 3778 // eintippen einer ALT-NUMPAD Kombination erzeugt wurden 3779 SalKeyEvent aKeyEvt; 3780 3781 if ( (wParam >= '0') && (wParam <= '9') ) 3782 aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_NUM + wParam - '0'); 3783 else if ( (wParam >= 'A') && (wParam <= 'Z') ) 3784 aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'A'); 3785 else if ( (wParam >= 'a') && (wParam <= 'z') ) 3786 aKeyEvt.mnCode = sal::static_int_cast<sal_uInt16>(KEYGROUP_ALPHA + wParam - 'a'); 3787 else if ( wParam == 0x0D ) // RETURN 3788 aKeyEvt.mnCode = KEY_RETURN; 3789 else if ( wParam == 0x1B ) // ESCAPE 3790 aKeyEvt.mnCode = KEY_ESCAPE; 3791 else if ( wParam == 0x09 ) // TAB 3792 aKeyEvt.mnCode = KEY_TAB; 3793 else if ( wParam == 0x20 ) // SPACE 3794 aKeyEvt.mnCode = KEY_SPACE; 3795 else 3796 aKeyEvt.mnCode = 0; 3797 3798 aKeyEvt.mnTime = GetMessageTime(); 3799 aKeyEvt.mnCode |= nModCode; 3800 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, wParam ); 3801 aKeyEvt.mnRepeat = nRepeat; 3802 nLastChar = 0; 3803 nLastVKChar = 0; 3804 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt ); 3805 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 3806 return nRet; 3807 } 3808 // #i11583#, MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition begins 3809 else if( nMsg == WM_UNICHAR ) 3810 { 3811 // If Windows is asking if we accept WM_UNICHAR, return TRUE 3812 if(wParam == UNICODE_NOCHAR) 3813 { 3814 rResult = TRUE; // ssa: this will actually return TRUE to windows 3815 return 1; // ...but this will only avoid calling the defwindowproc 3816 } 3817 3818 SalKeyEvent aKeyEvt; 3819 aKeyEvt.mnCode = nModCode; // Or should it be 0? - as this is always a character returned 3820 aKeyEvt.mnTime = GetMessageTime(); 3821 aKeyEvt.mnRepeat = 0; 3822 3823 if( wParam >= Uni_SupplementaryPlanesStart ) 3824 { 3825 // character is supplementary char in UTF-32 format - must be converted to UTF-16 supplementary pair 3826 // sal_Unicode ch = (sal_Unicode) Uni_UTF32ToSurrogate1(wParam); 3827 nLastChar = 0; 3828 nLastVKChar = 0; 3829 pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt ); 3830 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 3831 wParam = (sal_Unicode) Uni_UTF32ToSurrogate2( wParam ); 3832 } 3833 3834 aKeyEvt.mnCharCode = (sal_Unicode) wParam; 3835 3836 nLastChar = 0; 3837 nLastVKChar = 0; 3838 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt ); 3839 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 3840 3841 return nRet; 3842 } 3843 // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition ends 3844 else 3845 { 3846 // Bei Shift, Control und Menu schicken wir einen KeyModChange-Event 3847 if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) ) 3848 { 3849 SalKeyModEvent aModEvt; 3850 aModEvt.mnTime = GetMessageTime(); 3851 aModEvt.mnCode = nModCode; 3852 aModEvt.mnModKeyCode = 0; // no command events will be sent if this member is 0 3853 3854 sal_uInt16 tmpCode = 0; 3855 if( GetKeyState( VK_LSHIFT ) & 0x8000 ) 3856 tmpCode |= MODKEY_LSHIFT; 3857 if( GetKeyState( VK_RSHIFT ) & 0x8000 ) 3858 tmpCode |= MODKEY_RSHIFT; 3859 if( GetKeyState( VK_LCONTROL ) & 0x8000 ) 3860 tmpCode |= MODKEY_LMOD1; 3861 if( GetKeyState( VK_RCONTROL ) & 0x8000 ) 3862 tmpCode |= MODKEY_RMOD1; 3863 if( GetKeyState( VK_LMENU ) & 0x8000 ) 3864 tmpCode |= MODKEY_LMOD2; 3865 if( GetKeyState( VK_RMENU ) & 0x8000 ) 3866 tmpCode |= MODKEY_RMOD2; 3867 3868 if( tmpCode < nLastModKeyCode ) 3869 { 3870 aModEvt.mnModKeyCode = nLastModKeyCode; 3871 nLastModKeyCode = 0; 3872 bWaitForModKeyRelease = true; 3873 } 3874 else 3875 { 3876 if( !bWaitForModKeyRelease ) 3877 nLastModKeyCode = tmpCode; 3878 } 3879 3880 if( !tmpCode ) 3881 bWaitForModKeyRelease = false; 3882 3883 return pFrame->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt ); 3884 } 3885 else 3886 { 3887 SalKeyEvent aKeyEvt; 3888 sal_uInt16 nEvent; 3889 MSG aCharMsg; 3890 BOOL bCharPeek = FALSE; 3891 UINT nCharMsg = WM_CHAR; 3892 sal_Bool bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP); 3893 3894 nLastModKeyCode = 0; // make sure no modkey messages are sent if they belong to a hotkey (see above) 3895 aKeyEvt.mnCharCode = 0; 3896 aKeyEvt.mnCode = 0; 3897 3898 aKeyEvt.mnCode = ImplSalGetKeyCode( wParam ); 3899 if ( !bKeyUp ) 3900 { 3901 // check for charcode 3902 // Mit Hilfe von PeekMessage holen wir uns jetzt die 3903 // zugehoerige WM_CHAR Message, wenn vorhanden. 3904 // Diese WM_CHAR Message steht immer am Anfang der 3905 // Messagequeue. Ausserdem ist sichergestellt, dass immer 3906 // nur eine WM_CHAR Message in der Queue steht. 3907 bCharPeek = ImplPeekMessage( &aCharMsg, hWnd, 3908 WM_CHAR, WM_CHAR, PM_NOREMOVE | PM_NOYIELD ); 3909 if ( bCharPeek && (nDeadChar == aCharMsg.wParam) ) 3910 { 3911 bCharPeek = FALSE; 3912 nDeadChar = 0; 3913 3914 if ( wParam == VK_BACK ) 3915 { 3916 ImplPeekMessage( &aCharMsg, hWnd, 3917 nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD ); 3918 return 0; 3919 } 3920 } 3921 else 3922 { 3923 if ( !bCharPeek ) 3924 { 3925 bCharPeek = ImplPeekMessage( &aCharMsg, hWnd, 3926 WM_SYSCHAR, WM_SYSCHAR, PM_NOREMOVE | PM_NOYIELD ); 3927 nCharMsg = WM_SYSCHAR; 3928 } 3929 } 3930 if ( bCharPeek ) 3931 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, aCharMsg.wParam ); 3932 else 3933 aKeyEvt.mnCharCode = 0; 3934 3935 nLastChar = aKeyEvt.mnCharCode; 3936 nLastVKChar = wParam; 3937 } 3938 else 3939 { 3940 if ( wParam == nLastVKChar ) 3941 { 3942 aKeyEvt.mnCharCode = nLastChar; 3943 nLastChar = 0; 3944 nLastVKChar = 0; 3945 } 3946 } 3947 3948 if ( aKeyEvt.mnCode || aKeyEvt.mnCharCode ) 3949 { 3950 if ( bKeyUp ) 3951 nEvent = SALEVENT_KEYUP; 3952 else 3953 nEvent = SALEVENT_KEYINPUT; 3954 3955 aKeyEvt.mnTime = GetMessageTime(); 3956 aKeyEvt.mnCode |= nModCode; 3957 aKeyEvt.mnRepeat = nRepeat; 3958 3959 if( (nModCode & (KEY_MOD1|KEY_MOD2)) == (KEY_MOD1|KEY_MOD2) && 3960 aKeyEvt.mnCharCode ) 3961 { 3962 // this is actually AltGr and should not be handled as Alt 3963 aKeyEvt.mnCode &= ~(KEY_MOD1|KEY_MOD2); 3964 } 3965 3966 bIgnoreCharMsg = bCharPeek ? TRUE : FALSE; 3967 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt ); 3968 // independent part only reacts on keyup but Windows does not send 3969 // keyup for VK_HANJA 3970 if( aKeyEvt.mnCode == KEY_HANGUL_HANJA ) 3971 nRet = pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 3972 3973 bIgnoreCharMsg = FALSE; 3974 3975 // char-message, than remove or ignore 3976 if ( bCharPeek ) 3977 { 3978 nDeadChar = 0; 3979 if ( nRet ) 3980 { 3981 ImplPeekMessage( &aCharMsg, hWnd, 3982 nCharMsg, nCharMsg, PM_REMOVE | PM_NOYIELD ); 3983 } 3984 else 3985 bIgnoreCharMsg = TRUE; 3986 } 3987 3988 return nRet; 3989 } 3990 else 3991 return 0; 3992 } 3993 } 3994 } 3995 3996 // ----------------------------------------------------------------------- 3997 3998 long ImplHandleSalObjKeyMsg( HWND hWnd, UINT nMsg, 3999 WPARAM wParam, LPARAM lParam ) 4000 { 4001 if ( (nMsg == WM_KEYDOWN) || (nMsg == WM_KEYUP) ) 4002 { 4003 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4004 if ( !pFrame ) 4005 return 0; 4006 4007 sal_uInt16 nRepeat = LOWORD( lParam )-1; 4008 sal_uInt16 nModCode = 0; 4009 4010 // determine modifiers 4011 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 4012 nModCode |= KEY_SHIFT; 4013 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 4014 nModCode |= KEY_MOD1; 4015 if ( GetKeyState( VK_MENU ) & 0x8000 ) 4016 nModCode |= KEY_MOD2; 4017 4018 if ( (wParam != VK_SHIFT) && (wParam != VK_CONTROL) && (wParam != VK_MENU) ) 4019 { 4020 SalKeyEvent aKeyEvt; 4021 sal_uInt16 nEvent; 4022 sal_Bool bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP); 4023 4024 // convert KeyCode 4025 aKeyEvt.mnCode = ImplSalGetKeyCode( wParam ); 4026 aKeyEvt.mnCharCode = 0; 4027 4028 if ( aKeyEvt.mnCode ) 4029 { 4030 if ( bKeyUp ) 4031 nEvent = SALEVENT_KEYUP; 4032 else 4033 nEvent = SALEVENT_KEYINPUT; 4034 4035 aKeyEvt.mnTime = GetMessageTime(); 4036 aKeyEvt.mnCode |= nModCode; 4037 aKeyEvt.mnRepeat = nRepeat; 4038 long nRet = pFrame->CallCallback( nEvent, &aKeyEvt ); 4039 return nRet; 4040 } 4041 else 4042 return 0; 4043 } 4044 } 4045 4046 return 0; 4047 } 4048 4049 // ----------------------------------------------------------------------- 4050 4051 long ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam ) 4052 { 4053 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4054 if ( !pFrame ) 4055 return 0; 4056 4057 sal_uInt16 nRepeat = LOWORD( lParam )-1; 4058 sal_uInt16 nModCode = 0; 4059 sal_uInt16 cKeyCode = (sal_uInt16)wParam; 4060 4061 // determine modifiers 4062 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 4063 nModCode |= KEY_SHIFT; 4064 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 4065 nModCode |= KEY_MOD1; 4066 nModCode |= KEY_MOD2; 4067 4068 // KeyEvent zusammenbauen 4069 SalKeyEvent aKeyEvt; 4070 aKeyEvt.mnTime = GetMessageTime(); 4071 if ( (cKeyCode >= 48) && (cKeyCode <= 57) ) 4072 aKeyEvt.mnCode = KEY_0+(cKeyCode-48); 4073 else if ( (cKeyCode >= 65) && (cKeyCode <= 90) ) 4074 aKeyEvt.mnCode = KEY_A+(cKeyCode-65); 4075 else if ( (cKeyCode >= 97) && (cKeyCode <= 122) ) 4076 aKeyEvt.mnCode = KEY_A+(cKeyCode-97); 4077 else 4078 aKeyEvt.mnCode = 0; 4079 aKeyEvt.mnCode |= nModCode; 4080 aKeyEvt.mnCharCode = ImplGetCharCode( pFrame, cKeyCode ); 4081 aKeyEvt.mnRepeat = nRepeat; 4082 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt ); 4083 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 4084 return nRet; 4085 } 4086 4087 // ----------------------------------------------------------------------- 4088 4089 static bool ImplHandlePaintMsg( HWND hWnd ) 4090 { 4091 sal_Bool bMutex = FALSE; 4092 if ( ImplSalYieldMutexTryToAcquire() ) 4093 bMutex = TRUE; 4094 4095 // if we don't get the mutex, we can also change the clip region, 4096 // because other threads doesn't use the mutex from the main 4097 // thread --> see GetGraphics() 4098 4099 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4100 if ( pFrame ) 4101 { 4102 // Clip-Region muss zurueckgesetzt werden, da wir sonst kein 4103 // ordentliches Bounding-Rectangle bekommen 4104 if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion ) 4105 SelectClipRgn( pFrame->mpGraphics->getHDC(), 0 ); 4106 4107 // Laut Window-Doku soll man erst abfragen, ob ueberhaupt eine 4108 // Paint-Region anliegt 4109 if ( GetUpdateRect( hWnd, NULL, FALSE ) ) 4110 { 4111 // Call BeginPaint/EndPaint to query the rect and send 4112 // this Notofication to rect 4113 RECT aUpdateRect; 4114 PAINTSTRUCT aPs; 4115 BeginPaint( hWnd, &aPs ); 4116 CopyRect( &aUpdateRect, &aPs.rcPaint ); 4117 4118 // Paint 4119 // ClipRegion wieder herstellen 4120 if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion ) 4121 { 4122 SelectClipRgn( pFrame->mpGraphics->getHDC(), 4123 pFrame->mpGraphics->mhRegion ); 4124 } 4125 4126 if ( bMutex ) 4127 { 4128 SalPaintEvent aPEvt( aUpdateRect.left, aUpdateRect.top, aUpdateRect.right-aUpdateRect.left, aUpdateRect.bottom-aUpdateRect.top, pFrame->mbPresentation ); 4129 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt ); 4130 } 4131 else 4132 { 4133 RECT* pRect = new RECT; 4134 CopyRect( pRect, &aUpdateRect ); 4135 ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 ); 4136 } 4137 EndPaint( hWnd, &aPs ); 4138 } 4139 else 4140 { 4141 // ClipRegion wieder herstellen 4142 if ( pFrame->mpGraphics && pFrame->mpGraphics->mhRegion ) 4143 { 4144 SelectClipRgn( pFrame->mpGraphics->getHDC(), 4145 pFrame->mpGraphics->mhRegion ); 4146 } 4147 } 4148 } 4149 4150 if ( bMutex ) 4151 ImplSalYieldMutexRelease(); 4152 4153 return bMutex ? true : false; 4154 } 4155 4156 // ----------------------------------------------------------------------- 4157 4158 static void ImplHandlePaintMsg2( HWND hWnd, RECT* pRect ) 4159 { 4160 // Paint 4161 if ( ImplSalYieldMutexTryToAcquire() ) 4162 { 4163 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4164 if ( pFrame ) 4165 { 4166 SalPaintEvent aPEvt( pRect->left, pRect->top, pRect->right-pRect->left, pRect->bottom-pRect->top ); 4167 pFrame->CallCallback( SALEVENT_PAINT, &aPEvt ); 4168 } 4169 ImplSalYieldMutexRelease(); 4170 delete pRect; 4171 } 4172 else 4173 ImplPostMessage( hWnd, SAL_MSG_POSTPAINT, (WPARAM)pRect, 0 ); 4174 } 4175 4176 // ----------------------------------------------------------------------- 4177 4178 static void SetMaximizedFrameGeometry( HWND hWnd, WinSalFrame* pFrame, RECT* pParentRect ) 4179 { 4180 // calculate and set frame geometry of a maximized window - useful if the window is still hidden 4181 4182 // dualmonitor support: 4183 // Get screensize of the monitor with the mouse pointer 4184 4185 RECT aRectMouse; 4186 if( ! pParentRect ) 4187 { 4188 POINT pt; 4189 GetCursorPos( &pt ); 4190 aRectMouse.left = pt.x; 4191 aRectMouse.top = pt.y; 4192 aRectMouse.right = pt.x+2; 4193 aRectMouse.bottom = pt.y+2; 4194 pParentRect = &aRectMouse; 4195 } 4196 4197 RECT aRect; 4198 ImplSalGetWorkArea( hWnd, &aRect, pParentRect ); 4199 4200 // a maximized window has no other borders than the caption 4201 pFrame->maGeometry.nLeftDecoration = pFrame->maGeometry.nRightDecoration = pFrame->maGeometry.nBottomDecoration = 0; 4202 pFrame->maGeometry.nTopDecoration = pFrame->mbCaption ? GetSystemMetrics( SM_CYCAPTION ) : 0; 4203 4204 aRect.top += pFrame->maGeometry.nTopDecoration; 4205 pFrame->maGeometry.nX = aRect.left; 4206 pFrame->maGeometry.nY = aRect.top; 4207 pFrame->maGeometry.nWidth = aRect.right - aRect.left; 4208 pFrame->maGeometry.nHeight = aRect.bottom - aRect.top; 4209 } 4210 4211 static void UpdateFrameGeometry( HWND hWnd, WinSalFrame* pFrame ) 4212 { 4213 if( !pFrame ) 4214 return; 4215 4216 RECT aRect; 4217 GetWindowRect( hWnd, &aRect ); 4218 memset(&pFrame->maGeometry, 0, sizeof(SalFrameGeometry) ); 4219 4220 if ( IsIconic( hWnd ) ) 4221 return; 4222 4223 POINT aPt; 4224 aPt.x=0; 4225 aPt.y=0; 4226 ClientToScreen(hWnd, &aPt); 4227 int cx = aPt.x - aRect.left; 4228 pFrame->maGeometry.nTopDecoration = aPt.y - aRect.top; 4229 4230 pFrame->maGeometry.nLeftDecoration = cx; 4231 pFrame->maGeometry.nRightDecoration = cx; 4232 4233 pFrame->maGeometry.nX = aPt.x; 4234 pFrame->maGeometry.nY = aPt.y; 4235 4236 RECT aInnerRect; 4237 GetClientRect( hWnd, &aInnerRect ); 4238 if( aInnerRect.right ) 4239 { 4240 // improve right decoration 4241 aPt.x=aInnerRect.right; 4242 aPt.y=aInnerRect.top; 4243 ClientToScreen(hWnd, &aPt); 4244 pFrame->maGeometry.nRightDecoration = aRect.right - aPt.x; 4245 } 4246 if( aInnerRect.bottom ) // may be zero if window was not shown yet 4247 pFrame->maGeometry.nBottomDecoration += aRect.bottom - aPt.y - aInnerRect.bottom; 4248 else 4249 // bottom border is typically the same as left/right 4250 pFrame->maGeometry.nBottomDecoration = pFrame->maGeometry.nLeftDecoration; 4251 4252 int nWidth = aRect.right - aRect.left 4253 - pFrame->maGeometry.nRightDecoration - pFrame->maGeometry.nLeftDecoration; 4254 int nHeight = aRect.bottom - aRect.top 4255 - pFrame->maGeometry.nBottomDecoration - pFrame->maGeometry.nTopDecoration; 4256 // clamp to zero 4257 pFrame->maGeometry.nHeight = nHeight < 0 ? 0 : nHeight; 4258 pFrame->maGeometry.nWidth = nWidth < 0 ? 0 : nWidth; 4259 pFrame->updateScreenNumber(); 4260 } 4261 4262 // ----------------------------------------------------------------------- 4263 4264 static void ImplCallMoveHdl( HWND hWnd ) 4265 { 4266 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4267 if ( pFrame ) 4268 { 4269 pFrame->CallCallback( SALEVENT_MOVE, 0 ); 4270 // Um doppelte Paints von VCL und SAL zu vermeiden 4271 //if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow ) 4272 // UpdateWindow( hWnd ); 4273 } 4274 } 4275 4276 // ----------------------------------------------------------------------- 4277 4278 static void ImplCallClosePopupsHdl( HWND hWnd ) 4279 { 4280 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4281 if ( pFrame ) 4282 { 4283 pFrame->CallCallback( SALEVENT_CLOSEPOPUPS, 0 ); 4284 } 4285 } 4286 4287 // ----------------------------------------------------------------------- 4288 4289 static void ImplHandleMoveMsg( HWND hWnd ) 4290 { 4291 if ( ImplSalYieldMutexTryToAcquire() ) 4292 { 4293 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4294 if ( pFrame ) 4295 { 4296 UpdateFrameGeometry( hWnd, pFrame ); 4297 4298 if ( GetWindowStyle( hWnd ) & WS_VISIBLE ) 4299 pFrame->mbDefPos = FALSE; 4300 4301 // Gegen moegliche Rekursionen sichern 4302 if ( !pFrame->mbInMoveMsg ) 4303 { 4304 // Fenster im FullScreenModus wieder einpassen 4305 pFrame->mbInMoveMsg = TRUE; 4306 if ( pFrame->mbFullScreen ) 4307 ImplSalFrameFullScreenPos( pFrame ); 4308 pFrame->mbInMoveMsg = FALSE; 4309 } 4310 4311 // Status merken 4312 ImplSaveFrameState( pFrame ); 4313 4314 // Call Hdl 4315 //#93851 if we call this handler, VCL floating windows are not updated correctly 4316 ImplCallMoveHdl( hWnd ); 4317 4318 } 4319 4320 ImplSalYieldMutexRelease(); 4321 } 4322 else 4323 ImplPostMessage( hWnd, SAL_MSG_POSTMOVE, 0, 0 ); 4324 } 4325 4326 // ----------------------------------------------------------------------- 4327 4328 static void ImplCallSizeHdl( HWND hWnd ) 4329 { 4330 // Da Windows diese Messages auch senden kann, muss hier auch die 4331 // Solar-Semaphore beruecksichtigt werden 4332 if ( ImplSalYieldMutexTryToAcquire() ) 4333 { 4334 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4335 if ( pFrame ) 4336 { 4337 pFrame->CallCallback( SALEVENT_RESIZE, 0 ); 4338 // Um doppelte Paints von VCL und SAL zu vermeiden 4339 if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow ) 4340 UpdateWindow( hWnd ); 4341 } 4342 4343 ImplSalYieldMutexRelease(); 4344 } 4345 else 4346 ImplPostMessage( hWnd, SAL_MSG_POSTCALLSIZE, 0, 0 ); 4347 } 4348 4349 // ----------------------------------------------------------------------- 4350 4351 static void ImplHandleSizeMsg( HWND hWnd, WPARAM wParam, LPARAM lParam ) 4352 { 4353 if ( (wParam != SIZE_MAXSHOW) && (wParam != SIZE_MAXHIDE) ) 4354 { 4355 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4356 if ( pFrame ) 4357 { 4358 UpdateFrameGeometry( hWnd, pFrame ); 4359 4360 pFrame->mnWidth = (int)LOWORD(lParam); 4361 pFrame->mnHeight = (int)HIWORD(lParam); 4362 // Status merken 4363 ImplSaveFrameState( pFrame ); 4364 // Call Hdl 4365 ImplCallSizeHdl( hWnd ); 4366 } 4367 } 4368 } 4369 4370 // ----------------------------------------------------------------------- 4371 4372 static void ImplHandleFocusMsg( HWND hWnd ) 4373 { 4374 if ( ImplSalYieldMutexTryToAcquire() ) 4375 { 4376 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4377 if ( pFrame && !WinSalFrame::mbInReparent ) 4378 { 4379 // Query the actual status 4380 if ( ::GetFocus() == hWnd ) 4381 { 4382 if ( IsWindowVisible( hWnd ) && !pFrame->mbInShow ) 4383 UpdateWindow( hWnd ); 4384 4385 // Feststellen, ob wir IME unterstuetzen 4386 if ( pFrame->mbIME && pFrame->mhDefIMEContext ) 4387 { 4388 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_PROPERTY ); 4389 4390 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0; 4391 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0; 4392 pFrame->mbHandleIME = !pFrame->mbSpezIME; 4393 } 4394 4395 pFrame->CallCallback( SALEVENT_GETFOCUS, 0 ); 4396 } 4397 else 4398 { 4399 pFrame->CallCallback( SALEVENT_LOSEFOCUS, 0 ); 4400 } 4401 } 4402 4403 ImplSalYieldMutexRelease(); 4404 } 4405 else 4406 ImplPostMessage( hWnd, SAL_MSG_POSTFOCUS, 0, 0 ); 4407 } 4408 4409 // ----------------------------------------------------------------------- 4410 4411 static void ImplHandleCloseMsg( HWND hWnd ) 4412 { 4413 if ( ImplSalYieldMutexTryToAcquire() ) 4414 { 4415 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4416 if ( pFrame ) 4417 { 4418 pFrame->CallCallback( SALEVENT_CLOSE, 0 ); 4419 } 4420 4421 ImplSalYieldMutexRelease(); 4422 } 4423 else 4424 ImplPostMessage( hWnd, WM_CLOSE, 0, 0 ); 4425 } 4426 4427 // ----------------------------------------------------------------------- 4428 4429 static long ImplHandleShutDownMsg( HWND hWnd ) 4430 { 4431 ImplSalYieldMutexAcquireWithWait(); 4432 long nRet = 0; 4433 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4434 if ( pFrame ) 4435 { 4436 nRet = pFrame->CallCallback( SALEVENT_SHUTDOWN, 0 ); 4437 } 4438 ImplSalYieldMutexRelease(); 4439 return nRet; 4440 } 4441 4442 // ----------------------------------------------------------------------- 4443 4444 static void ImplHandleSettingsChangeMsg( HWND hWnd, UINT nMsg, 4445 WPARAM wParam, LPARAM lParam ) 4446 { 4447 sal_uInt16 nSalEvent = SALEVENT_SETTINGSCHANGED; 4448 4449 if ( nMsg == WM_DEVMODECHANGE ) 4450 nSalEvent = SALEVENT_PRINTERCHANGED; 4451 else if ( nMsg == WM_DISPLAYCHANGE ) 4452 nSalEvent = SALEVENT_DISPLAYCHANGED; 4453 else if ( nMsg == WM_FONTCHANGE ) 4454 nSalEvent = SALEVENT_FONTCHANGED; 4455 else if ( nMsg == WM_TIMECHANGE ) 4456 nSalEvent = SALEVENT_DATETIMECHANGED; 4457 else if ( nMsg == WM_WININICHANGE ) 4458 { 4459 if ( lParam ) 4460 { 4461 if ( ImplSalWICompareAscii( (const wchar_t*)lParam, "devices" ) == 0 ) 4462 nSalEvent = SALEVENT_PRINTERCHANGED; 4463 } 4464 } 4465 4466 if ( nMsg == WM_SETTINGCHANGE ) 4467 { 4468 if ( wParam == SPI_SETWHEELSCROLLLINES ) 4469 aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines(); 4470 else if( wParam == SPI_SETWHEELSCROLLCHARS ) 4471 aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars(); 4472 } 4473 4474 if ( WM_SYSCOLORCHANGE == nMsg && GetSalData()->mhDitherPal ) 4475 ImplUpdateSysColorEntries(); 4476 4477 ImplSalYieldMutexAcquireWithWait(); 4478 4479 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4480 if ( pFrame ) 4481 { 4482 if ( (nMsg == WM_DISPLAYCHANGE) || (nMsg == WM_WININICHANGE) ) 4483 { 4484 if ( pFrame->mbFullScreen ) 4485 ImplSalFrameFullScreenPos( pFrame ); 4486 } 4487 4488 pFrame->CallCallback( nSalEvent, 0 ); 4489 } 4490 4491 ImplSalYieldMutexRelease(); 4492 } 4493 4494 // ----------------------------------------------------------------------- 4495 4496 static void ImplHandleUserEvent( HWND hWnd, LPARAM lParam ) 4497 { 4498 ImplSalYieldMutexAcquireWithWait(); 4499 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4500 if ( pFrame ) 4501 { 4502 pFrame->CallCallback( SALEVENT_USEREVENT, (void*)lParam ); 4503 } 4504 ImplSalYieldMutexRelease(); 4505 } 4506 4507 // ----------------------------------------------------------------------- 4508 4509 static void ImplHandleForcePalette( HWND hWnd ) 4510 { 4511 SalData* pSalData = GetSalData(); 4512 HPALETTE hPal = pSalData->mhDitherPal; 4513 if ( hPal ) 4514 { 4515 if ( !ImplSalYieldMutexTryToAcquire() ) 4516 { 4517 ImplPostMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 ); 4518 return; 4519 } 4520 4521 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4522 if ( pFrame && pFrame->mpGraphics ) 4523 { 4524 WinSalGraphics* pGraphics = pFrame->mpGraphics; 4525 if ( pGraphics && pGraphics->mhDefPal ) 4526 { 4527 SelectPalette( pGraphics->getHDC(), hPal, FALSE ); 4528 if ( RealizePalette( pGraphics->getHDC() ) ) 4529 { 4530 InvalidateRect( hWnd, NULL, FALSE ); 4531 UpdateWindow( hWnd ); 4532 pFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 ); 4533 } 4534 } 4535 } 4536 4537 ImplSalYieldMutexRelease(); 4538 } 4539 } 4540 4541 // ----------------------------------------------------------------------- 4542 4543 static LRESULT ImplHandlePalette( sal_Bool bFrame, HWND hWnd, UINT nMsg, 4544 WPARAM wParam, LPARAM lParam, int& rDef ) 4545 { 4546 SalData* pSalData = GetSalData(); 4547 HPALETTE hPal = pSalData->mhDitherPal; 4548 if ( !hPal ) 4549 return 0; 4550 4551 rDef = FALSE; 4552 if ( pSalData->mbInPalChange ) 4553 return 0; 4554 4555 if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) ) 4556 { 4557 if ( (HWND)wParam == hWnd ) 4558 return 0; 4559 } 4560 4561 sal_Bool bReleaseMutex = FALSE; 4562 if ( (nMsg == WM_QUERYNEWPALETTE) || (nMsg == WM_PALETTECHANGED) ) 4563 { 4564 // Da Windows diese Messages auch sendet, muss hier auch die 4565 // Solar-Semaphore beruecksichtigt werden 4566 if ( ImplSalYieldMutexTryToAcquire() ) 4567 bReleaseMutex = TRUE; 4568 else if ( nMsg == WM_QUERYNEWPALETTE ) 4569 ImplPostMessage( hWnd, SAL_MSG_POSTQUERYNEWPAL, wParam, lParam ); 4570 else /* ( nMsg == WM_PALETTECHANGED ) */ 4571 ImplPostMessage( hWnd, SAL_MSG_POSTPALCHANGED, wParam, lParam ); 4572 } 4573 4574 WinSalVirtualDevice*pTempVD; 4575 WinSalFrame* pTempFrame; 4576 WinSalGraphics* pGraphics; 4577 HDC hDC; 4578 HPALETTE hOldPal; 4579 UINT nCols; 4580 sal_Bool bStdDC; 4581 sal_Bool bUpdate; 4582 4583 pSalData->mbInPalChange = TRUE; 4584 4585 // Alle Paletten in VirDevs und Frames zuruecksetzen 4586 pTempVD = pSalData->mpFirstVD; 4587 while ( pTempVD ) 4588 { 4589 pGraphics = pTempVD->mpGraphics; 4590 if ( pGraphics->mhDefPal ) 4591 { 4592 SelectPalette( pGraphics->getHDC(), 4593 pGraphics->mhDefPal, 4594 TRUE ); 4595 } 4596 pTempVD = pTempVD->mpNext; 4597 } 4598 pTempFrame = pSalData->mpFirstFrame; 4599 while ( pTempFrame ) 4600 { 4601 pGraphics = pTempFrame->mpGraphics; 4602 if ( pGraphics && pGraphics->mhDefPal ) 4603 { 4604 SelectPalette( pGraphics->getHDC(), 4605 pGraphics->mhDefPal, 4606 TRUE ); 4607 } 4608 pTempFrame = pTempFrame->mpNextFrame; 4609 } 4610 4611 // Palette neu realizen 4612 WinSalFrame* pFrame = NULL; 4613 if ( bFrame ) 4614 pFrame = GetWindowPtr( hWnd ); 4615 if ( pFrame && pFrame->mpGraphics ) 4616 { 4617 hDC = pFrame->mpGraphics->getHDC(); 4618 bStdDC = TRUE; 4619 } 4620 else 4621 { 4622 hDC = GetDC( hWnd ); 4623 bStdDC = FALSE; 4624 } 4625 UnrealizeObject( hPal ); 4626 hOldPal = SelectPalette( hDC, hPal, TRUE ); 4627 nCols = RealizePalette( hDC ); 4628 bUpdate = nCols != 0; 4629 if ( !bStdDC ) 4630 { 4631 SelectPalette( hDC, hOldPal, TRUE ); 4632 ReleaseDC( hWnd, hDC ); 4633 } 4634 4635 // Alle Paletten in VirDevs und Frames neu setzen 4636 pTempVD = pSalData->mpFirstVD; 4637 while ( pTempVD ) 4638 { 4639 pGraphics = pTempVD->mpGraphics; 4640 if ( pGraphics->mhDefPal ) 4641 { 4642 SelectPalette( pGraphics->getHDC(), hPal, TRUE ); 4643 RealizePalette( pGraphics->getHDC() ); 4644 } 4645 pTempVD = pTempVD->mpNext; 4646 } 4647 pTempFrame = pSalData->mpFirstFrame; 4648 while ( pTempFrame ) 4649 { 4650 if ( pTempFrame != pFrame ) 4651 { 4652 pGraphics = pTempFrame->mpGraphics; 4653 if ( pGraphics && pGraphics->mhDefPal ) 4654 { 4655 SelectPalette( pGraphics->getHDC(), hPal, TRUE ); 4656 if ( RealizePalette( pGraphics->getHDC() ) ) 4657 bUpdate = TRUE; 4658 } 4659 } 4660 pTempFrame = pTempFrame->mpNextFrame; 4661 } 4662 4663 // Wenn sich Farben geaendert haben, dann die Fenster updaten 4664 if ( bUpdate ) 4665 { 4666 pTempFrame = pSalData->mpFirstFrame; 4667 while ( pTempFrame ) 4668 { 4669 pGraphics = pTempFrame->mpGraphics; 4670 if ( pGraphics && pGraphics->mhDefPal ) 4671 { 4672 InvalidateRect( pTempFrame->mhWnd, NULL, FALSE ); 4673 UpdateWindow( pTempFrame->mhWnd ); 4674 pTempFrame->CallCallback( SALEVENT_DISPLAYCHANGED, 0 ); 4675 } 4676 pTempFrame = pTempFrame->mpNextFrame; 4677 } 4678 } 4679 4680 pSalData->mbInPalChange = FALSE; 4681 4682 if ( bReleaseMutex ) 4683 ImplSalYieldMutexRelease(); 4684 4685 if ( nMsg == WM_PALETTECHANGED ) 4686 return 0; 4687 else 4688 return nCols; 4689 } 4690 4691 // ----------------------------------------------------------------------- 4692 4693 static int ImplHandleMinMax( HWND hWnd, LPARAM lParam ) 4694 { 4695 int bRet = FALSE; 4696 4697 if ( ImplSalYieldMutexTryToAcquire() ) 4698 { 4699 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 4700 if ( pFrame ) 4701 { 4702 MINMAXINFO* pMinMax = (MINMAXINFO*)lParam; 4703 4704 if ( pFrame->mbFullScreen ) 4705 { 4706 int nX; 4707 int nY; 4708 int nDX; 4709 int nDY; 4710 ImplSalCalcFullScreenSize( pFrame, nX, nY, nDX, nDY ); 4711 4712 if ( pMinMax->ptMaxPosition.x > nX ) 4713 pMinMax->ptMaxPosition.x = nX; 4714 if ( pMinMax->ptMaxPosition.y > nY ) 4715 pMinMax->ptMaxPosition.y = nY; 4716 4717 if ( pMinMax->ptMaxSize.x < nDX ) 4718 pMinMax->ptMaxSize.x = nDX; 4719 if ( pMinMax->ptMaxSize.y < nDY ) 4720 pMinMax->ptMaxSize.y = nDY; 4721 if ( pMinMax->ptMaxTrackSize.x < nDX ) 4722 pMinMax->ptMaxTrackSize.x = nDX; 4723 if ( pMinMax->ptMaxTrackSize.y < nDY ) 4724 pMinMax->ptMaxTrackSize.y = nDY; 4725 4726 pMinMax->ptMinTrackSize.x = nDX; 4727 pMinMax->ptMinTrackSize.y = nDY; 4728 4729 bRet = TRUE; 4730 } 4731 4732 if ( pFrame->mnMinWidth || pFrame->mnMinHeight ) 4733 { 4734 int nWidth = pFrame->mnMinWidth; 4735 int nHeight = pFrame->mnMinHeight; 4736 4737 ImplSalAddBorder( pFrame, nWidth, nHeight ); 4738 4739 if ( pMinMax->ptMinTrackSize.x < nWidth ) 4740 pMinMax->ptMinTrackSize.x = nWidth; 4741 if ( pMinMax->ptMinTrackSize.y < nHeight ) 4742 pMinMax->ptMinTrackSize.y = nHeight; 4743 } 4744 4745 if ( pFrame->mnMaxWidth || pFrame->mnMaxHeight ) 4746 { 4747 int nWidth = pFrame->mnMaxWidth; 4748 int nHeight = pFrame->mnMaxHeight; 4749 4750 ImplSalAddBorder( pFrame, nWidth, nHeight ); 4751 4752 if( nWidth > 0 && nHeight > 0 ) // protect against int overflow due to INT_MAX initialization 4753 { 4754 if ( pMinMax->ptMaxTrackSize.x > nWidth ) 4755 pMinMax->ptMaxTrackSize.x = nWidth; 4756 if ( pMinMax->ptMaxTrackSize.y > nHeight ) 4757 pMinMax->ptMaxTrackSize.y = nHeight; 4758 } 4759 } 4760 } 4761 4762 ImplSalYieldMutexRelease(); 4763 } 4764 4765 return bRet; 4766 } 4767 4768 // ----------------------------------------------------------------------- 4769 4770 // retrieves the SalMenuItem pointer from a hMenu 4771 // the pointer is stored in every item, so if no position 4772 // is specified we just use the first item (i.e. pos=0) 4773 // if bByPosition is FALSE then nPos denotes a menu id instead of a position 4774 static WinSalMenuItem* ImplGetSalMenuItem( HMENU hMenu, UINT nPos, sal_Bool bByPosition=TRUE ) 4775 { 4776 DWORD err=0; 4777 4778 MENUITEMINFOW mi; 4779 memset(&mi, 0, sizeof(mi)); 4780 mi.cbSize = sizeof( mi ); 4781 mi.fMask = MIIM_DATA; 4782 if( !GetMenuItemInfoW( hMenu, nPos, bByPosition, &mi) ) 4783 err = GetLastError(); 4784 4785 return (WinSalMenuItem *) mi.dwItemData; 4786 } 4787 4788 // returns the index of the currently selected item if any or -1 4789 static int ImplGetSelectedIndex( HMENU hMenu ) 4790 { 4791 DWORD err=0; 4792 4793 MENUITEMINFOW mi; 4794 memset(&mi, 0, sizeof(mi)); 4795 mi.cbSize = sizeof( mi ); 4796 mi.fMask = MIIM_STATE; 4797 int n = GetMenuItemCount( hMenu ); 4798 if( n != -1 ) 4799 { 4800 for(int i=0; i<n; i++ ) 4801 { 4802 if( !GetMenuItemInfoW( hMenu, i, TRUE, &mi) ) 4803 err = GetLastError(); 4804 else 4805 { 4806 if( mi.fState & MFS_HILITE ) 4807 return i; 4808 } 4809 } 4810 } 4811 return -1; 4812 } 4813 4814 static int ImplMenuChar( HWND, WPARAM wParam, LPARAM lParam ) 4815 { 4816 int nRet = MNC_IGNORE; 4817 HMENU hMenu = (HMENU) lParam; 4818 String aMnemonic; 4819 aMnemonic.AssignAscii("&"); 4820 aMnemonic.Append( (sal_Unicode) LOWORD(wParam) ); 4821 aMnemonic.ToLowerAscii(); // we only have ascii mnemonics 4822 4823 // search the mnemonic in the current menu 4824 int nItemCount = GetMenuItemCount( hMenu ); 4825 int nFound = 0; 4826 int idxFound = -1; 4827 int idxSelected = ImplGetSelectedIndex( hMenu ); 4828 int idx = idxSelected != -1 ? idxSelected+1 : 0; // if duplicate mnemonics cycle through menu 4829 for( int i=0; i< nItemCount; i++, idx++ ) 4830 { 4831 WinSalMenuItem* pSalMenuItem = ImplGetSalMenuItem( hMenu, idx % nItemCount ); 4832 if( !pSalMenuItem ) 4833 continue; 4834 String aStr = pSalMenuItem->mText; 4835 aStr.ToLowerAscii(); 4836 if( aStr.Search( aMnemonic ) != STRING_NOTFOUND) 4837 { 4838 if( idxFound == -1 ) 4839 idxFound = idx % nItemCount; 4840 if( nFound++ ) 4841 break; // duplicate found 4842 } 4843 } 4844 if( nFound == 1 ) 4845 nRet = MAKELRESULT( idxFound, MNC_EXECUTE ); 4846 else 4847 // duplicate mnemonics, just select the next occurrence 4848 nRet = MAKELRESULT( idxFound, MNC_SELECT ); 4849 4850 return nRet; 4851 } 4852 4853 static int ImplMeasureItem( HWND hWnd, WPARAM wParam, LPARAM lParam ) 4854 { 4855 int nRet = 0; 4856 if( !wParam ) 4857 { 4858 // request was sent by a menu 4859 nRet = 1; 4860 MEASUREITEMSTRUCT *pMI = (LPMEASUREITEMSTRUCT) lParam; 4861 if( pMI->CtlType != ODT_MENU ) 4862 return 0; 4863 4864 WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pMI->itemData; 4865 if( !pSalMenuItem ) 4866 return 0; 4867 4868 HDC hdc = GetDC( hWnd ); 4869 SIZE strSize; 4870 4871 NONCLIENTMETRICS ncm; 4872 memset( &ncm, 0, sizeof(ncm) ); 4873 ncm.cbSize = sizeof( ncm ); 4874 SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 ); 4875 4876 // Assume every menu item can be default and printed bold 4877 //ncm.lfMenuFont.lfWeight = FW_BOLD; 4878 4879 HFONT hfntOld = (HFONT) SelectObject(hdc, (HFONT) CreateFontIndirect( &ncm.lfMenuFont )); 4880 4881 // menu text and accelerator 4882 String aStr(pSalMenuItem->mText.GetBuffer() ); 4883 if( pSalMenuItem->mAccelText.Len() ) 4884 { 4885 aStr.AppendAscii(" "); 4886 aStr.Append( pSalMenuItem->mAccelText ); 4887 } 4888 GetTextExtentPoint32W( hdc, (LPWSTR) aStr.GetBuffer(), 4889 aStr.Len(), &strSize ); 4890 4891 // image 4892 Size bmpSize( 16, 16 ); 4893 //if( !!pSalMenuItem->maBitmap ) 4894 // bmpSize = pSalMenuItem->maBitmap.GetSizePixel(); 4895 4896 // checkmark 4897 Size checkSize( GetSystemMetrics( SM_CXMENUCHECK ), GetSystemMetrics( SM_CYMENUCHECK ) ); 4898 4899 pMI->itemWidth = checkSize.Width() + 3 + bmpSize.Width() + 3 + strSize.cx; 4900 pMI->itemHeight = Max( Max( checkSize.Height(), bmpSize.Height() ), strSize.cy ); 4901 pMI->itemHeight += 4; 4902 4903 DeleteObject( SelectObject(hdc, hfntOld) ); 4904 ReleaseDC( hWnd, hdc ); 4905 } 4906 4907 return nRet; 4908 } 4909 4910 static int ImplDrawItem(HWND, WPARAM wParam, LPARAM lParam ) 4911 { 4912 int nRet = 0; 4913 DWORD err = 0; 4914 if( !wParam ) 4915 { 4916 // request was sent by a menu 4917 nRet = 1; 4918 DRAWITEMSTRUCT *pDI = (LPDRAWITEMSTRUCT) lParam; 4919 if( pDI->CtlType != ODT_MENU ) 4920 return 0; 4921 4922 WinSalMenuItem *pSalMenuItem = (WinSalMenuItem *) pDI->itemData; 4923 if( !pSalMenuItem ) 4924 return 0; 4925 4926 COLORREF clrPrevText, clrPrevBkgnd; 4927 HFONT hfntOld; 4928 HBRUSH hbrOld; 4929 sal_Bool fChecked = (pDI->itemState & ODS_CHECKED) ? TRUE : FALSE; 4930 sal_Bool fSelected = (pDI->itemState & ODS_SELECTED) ? TRUE : FALSE; 4931 sal_Bool fDisabled = (pDI->itemState & (ODS_DISABLED | ODS_GRAYED)) ? TRUE : FALSE; 4932 4933 // Set the appropriate foreground and background colors. 4934 RECT aRect = pDI->rcItem; 4935 4936 clrPrevBkgnd = SetBkColor( pDI->hDC, GetSysColor( COLOR_MENU ) ); 4937 4938 if ( fDisabled ) 4939 clrPrevText = SetTextColor( pDI->hDC, GetSysColor( COLOR_GRAYTEXT ) ); 4940 else 4941 clrPrevText = SetTextColor( pDI->hDC, GetSysColor( fSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT ) ); 4942 4943 DWORD colBackground = GetSysColor( fSelected ? COLOR_HIGHLIGHT : COLOR_MENU ); 4944 if ( fSelected ) 4945 clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground ); 4946 else 4947 clrPrevBkgnd = SetBkColor( pDI->hDC, colBackground ); 4948 4949 hbrOld = (HBRUSH)SelectObject( pDI->hDC, CreateSolidBrush( GetBkColor( pDI->hDC ) ) ); 4950 4951 // Fill background 4952 if(!PatBlt( pDI->hDC, aRect.left, aRect.top, aRect.right-aRect.left, aRect.bottom-aRect.top, PATCOPY )) 4953 err = GetLastError(); 4954 4955 int lineHeight = aRect.bottom-aRect.top; 4956 4957 int x = aRect.left; 4958 int y = aRect.top; 4959 4960 int checkWidth = GetSystemMetrics( SM_CXMENUCHECK ); 4961 int checkHeight = GetSystemMetrics( SM_CYMENUCHECK ); 4962 if( fChecked ) 4963 { 4964 RECT r; 4965 r.left = 0; 4966 r.top = 0; 4967 r.right = checkWidth; 4968 r.bottom = checkWidth; 4969 HDC memDC = CreateCompatibleDC( pDI->hDC ); 4970 HBITMAP memBmp = CreateCompatibleBitmap( pDI->hDC, checkWidth, checkHeight ); 4971 HBITMAP hOldBmp = (HBITMAP) SelectObject( memDC, memBmp ); 4972 DrawFrameControl( memDC, &r, DFC_MENU, DFCS_MENUCHECK ); 4973 BitBlt( pDI->hDC, x, y+(lineHeight-checkHeight)/2, checkWidth, checkHeight, memDC, 0, 0, SRCAND ); 4974 DeleteObject( SelectObject( memDC, hOldBmp ) ); 4975 DeleteDC( memDC ); 4976 } 4977 x += checkWidth+3; 4978 4979 //Size bmpSize = aBitmap.GetSizePixel(); 4980 Size bmpSize(16, 16); 4981 if( !!pSalMenuItem->maBitmap ) 4982 { 4983 Bitmap aBitmap( pSalMenuItem->maBitmap ); 4984 4985 // set transparent pixels to background color 4986 if( fDisabled ) 4987 colBackground = RGB(255,255,255); 4988 aBitmap.Replace( Color( COL_LIGHTMAGENTA ), 4989 Color( GetRValue(colBackground),GetGValue(colBackground),GetBValue(colBackground) ), 0); 4990 4991 WinSalBitmap* pSalBmp = static_cast<WinSalBitmap*>(aBitmap.ImplGetImpBitmap()->ImplGetSalBitmap()); 4992 HGLOBAL hDrawDIB = pSalBmp->ImplGethDIB(); 4993 4994 if( hDrawDIB ) 4995 { 4996 PBITMAPINFO pBI = (PBITMAPINFO) GlobalLock( hDrawDIB ); 4997 PBITMAPINFOHEADER pBIH = (PBITMAPINFOHEADER) pBI; 4998 PBYTE pBits = (PBYTE) pBI + *(DWORD*) pBI + 4999 pSalBmp->ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD ); 5000 5001 HBITMAP hBmp = CreateDIBitmap( pDI->hDC, pBIH, CBM_INIT, pBits, pBI, DIB_RGB_COLORS ); 5002 GlobalUnlock( hDrawDIB ); 5003 5004 HBRUSH hbrIcon = CreateSolidBrush( GetSysColor( COLOR_GRAYTEXT ) ); 5005 DrawStateW( pDI->hDC, (HBRUSH)hbrIcon, (DRAWSTATEPROC)NULL, (LPARAM)hBmp, (WPARAM)0, 5006 x, y+(lineHeight-bmpSize.Height())/2, bmpSize.Width(), bmpSize.Height(), 5007 DST_BITMAP | (fDisabled ? (fSelected ? DSS_MONO : DSS_DISABLED) : DSS_NORMAL) ); 5008 5009 DeleteObject( hbrIcon ); 5010 DeleteObject( hBmp ); 5011 } 5012 5013 } 5014 x += bmpSize.Width() + 3; 5015 aRect.left = x; 5016 5017 NONCLIENTMETRICS ncm; 5018 memset( &ncm, 0, sizeof(ncm) ); 5019 ncm.cbSize = sizeof( ncm ); 5020 SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, (PVOID) &ncm, 0 ); 5021 5022 // Print default menu entry with bold font 5023 //if ( pDI->itemState & ODS_DEFAULT ) 5024 // ncm.lfMenuFont.lfWeight = FW_BOLD; 5025 5026 hfntOld = (HFONT) SelectObject(pDI->hDC, (HFONT) CreateFontIndirect( &ncm.lfMenuFont )); 5027 5028 SIZE strSize; 5029 String aStr( pSalMenuItem->mText.GetBuffer() ); 5030 GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(), 5031 aStr.Len(), &strSize ); 5032 5033 if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL, 5034 (LPARAM)(LPWSTR) aStr.GetBuffer(), 5035 (WPARAM)0, aRect.left, aRect.top + (lineHeight - strSize.cy)/2, 0, 0, 5036 DST_PREFIXTEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) ) 5037 err = GetLastError(); 5038 5039 if( pSalMenuItem->mAccelText.Len() ) 5040 { 5041 SIZE strSizeA; 5042 aStr = pSalMenuItem->mAccelText; 5043 GetTextExtentPoint32W( pDI->hDC, (LPWSTR) aStr.GetBuffer(), 5044 aStr.Len(), &strSizeA ); 5045 TEXTMETRIC tm; 5046 GetTextMetrics( pDI->hDC, &tm ); 5047 5048 // position the accelerator string to the right but leave space for the 5049 // (potential) submenu arrow (tm.tmMaxCharWidth) 5050 if(!DrawStateW( pDI->hDC, (HBRUSH)NULL, (DRAWSTATEPROC)NULL, 5051 (LPARAM)(LPWSTR) aStr.GetBuffer(), 5052 (WPARAM)0, aRect.right-strSizeA.cx-tm.tmMaxCharWidth, aRect.top + (lineHeight - strSizeA.cy)/2, 0, 0, 5053 DST_TEXT | (fDisabled && !fSelected ? DSS_DISABLED : DSS_NORMAL) ) ) 5054 err = GetLastError(); 5055 } 5056 5057 // Restore the original font and colors. 5058 DeleteObject( SelectObject( pDI->hDC, hbrOld ) ); 5059 DeleteObject( SelectObject( pDI->hDC, hfntOld) ); 5060 SetTextColor(pDI->hDC, clrPrevText); 5061 SetBkColor(pDI->hDC, clrPrevBkgnd); 5062 } 5063 return nRet; 5064 } 5065 5066 static int ImplHandleMenuActivate( HWND hWnd, WPARAM wParam, LPARAM ) 5067 { 5068 // Menu activation 5069 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5070 if ( !pFrame ) 5071 return 0; 5072 5073 HMENU hMenu = (HMENU) wParam; 5074 // WORD nPos = LOWORD (lParam); 5075 // sal_Bool bWindowMenu = (sal_Bool) HIWORD(lParam); 5076 5077 // Send activate and deactivate together, so we have not keep track of opened menus 5078 // this will be enough to have the menus updated correctly 5079 SalMenuEvent aMenuEvt; 5080 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, 0 ); 5081 if( pSalMenuItem ) 5082 aMenuEvt.mpMenu = pSalMenuItem->mpMenu; 5083 else 5084 aMenuEvt.mpMenu = NULL; 5085 5086 long nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt ); 5087 if( nRet ) 5088 nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt ); 5089 if( nRet ) 5090 pFrame->mLastActivatedhMenu = hMenu; 5091 5092 return (nRet!=0); 5093 } 5094 5095 static int ImplHandleMenuSelect( HWND hWnd, WPARAM wParam, LPARAM lParam ) 5096 { 5097 // Menu selection 5098 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5099 if ( !pFrame ) 5100 return 0; 5101 5102 WORD nId = LOWORD(wParam); // menu item or submenu index 5103 WORD nFlags = HIWORD(wParam); 5104 HMENU hMenu = (HMENU) lParam; 5105 5106 // check if we have to process the message 5107 if( !GetSalData()->IsKnownMenuHandle( hMenu ) ) 5108 return 0; 5109 5110 sal_Bool bByPosition = FALSE; 5111 if( nFlags & MF_POPUP ) 5112 bByPosition = TRUE; 5113 5114 long nRet = 0; 5115 if ( hMenu && !pFrame->mLastActivatedhMenu ) 5116 { 5117 // we never activated a menu (i.e. no WM_INITMENUPOPUP has occurred yet) 5118 // which means this must be the menubar -> send activation/deactivation 5119 SalMenuEvent aMenuEvt; 5120 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, bByPosition ); 5121 if( pSalMenuItem ) 5122 aMenuEvt.mpMenu = pSalMenuItem->mpMenu; 5123 else 5124 aMenuEvt.mpMenu = NULL; 5125 5126 nRet = pFrame->CallCallback( SALEVENT_MENUACTIVATE, &aMenuEvt ); 5127 if( nRet ) 5128 nRet = pFrame->CallCallback( SALEVENT_MENUDEACTIVATE, &aMenuEvt ); 5129 if( nRet ) 5130 pFrame->mLastActivatedhMenu = hMenu; 5131 } 5132 5133 if( !hMenu && nFlags == 0xFFFF ) 5134 { 5135 // all menus are closed, reset activation logic 5136 pFrame->mLastActivatedhMenu = NULL; 5137 } 5138 5139 if( hMenu ) 5140 { 5141 // hMenu must be saved, as it is not passed in WM_COMMAND which always occurs after a selection 5142 // if a menu is closed due to a command selection then hMenu is NULL, but WM_COMMAND comes later 5143 // so we must not overwrite it in this case 5144 pFrame->mSelectedhMenu = hMenu; 5145 5146 // send highlight event 5147 if( nFlags & MF_POPUP ) 5148 { 5149 // submenu selected 5150 // wParam now carries an index instead of an id -> retrieve id 5151 MENUITEMINFOW mi; 5152 memset(&mi, 0, sizeof(mi)); 5153 mi.cbSize = sizeof( mi ); 5154 mi.fMask = MIIM_ID; 5155 if( GetMenuItemInfoW( hMenu, LOWORD(wParam), TRUE, &mi) ) 5156 nId = sal::static_int_cast<WORD>(mi.wID); 5157 } 5158 5159 SalMenuEvent aMenuEvt; 5160 aMenuEvt.mnId = nId; 5161 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( hMenu, nId, FALSE ); 5162 if( pSalMenuItem ) 5163 aMenuEvt.mpMenu = pSalMenuItem->mpMenu; 5164 else 5165 aMenuEvt.mpMenu = NULL; 5166 5167 nRet = pFrame->CallCallback( SALEVENT_MENUHIGHLIGHT, &aMenuEvt ); 5168 } 5169 5170 return (nRet != 0); 5171 } 5172 5173 static int ImplHandleCommand( HWND hWnd, WPARAM wParam, LPARAM ) 5174 { 5175 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5176 if ( !pFrame ) 5177 return 0; 5178 5179 long nRet = 0; 5180 if( !HIWORD(wParam) ) 5181 { 5182 // Menu command 5183 WORD nId = LOWORD(wParam); 5184 if( nId ) // zero for separators 5185 { 5186 SalMenuEvent aMenuEvt; 5187 aMenuEvt.mnId = nId; 5188 WinSalMenuItem *pSalMenuItem = ImplGetSalMenuItem( pFrame->mSelectedhMenu, nId, FALSE ); 5189 if( pSalMenuItem ) 5190 aMenuEvt.mpMenu = pSalMenuItem->mpMenu; 5191 else 5192 aMenuEvt.mpMenu = NULL; 5193 5194 nRet = pFrame->CallCallback( SALEVENT_MENUCOMMAND, &aMenuEvt ); 5195 } 5196 } 5197 return (nRet != 0); 5198 } 5199 5200 static int ImplHandleSysCommand( HWND hWnd, WPARAM wParam, LPARAM lParam ) 5201 { 5202 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5203 if ( !pFrame ) 5204 return 0; 5205 5206 WPARAM nCommand = wParam & 0xFFF0; 5207 5208 if ( pFrame->mbFullScreen ) 5209 { 5210 BOOL bMaximize = IsZoomed( pFrame->mhWnd ); 5211 BOOL bMinimize = IsIconic( pFrame->mhWnd ); 5212 if ( (nCommand == SC_SIZE) || 5213 (!bMinimize && (nCommand == SC_MOVE)) || 5214 (!bMaximize && (nCommand == SC_MAXIMIZE)) || 5215 (bMaximize && (nCommand == SC_RESTORE)) ) 5216 { 5217 MessageBeep( 0 ); 5218 return TRUE; 5219 } 5220 } 5221 5222 if ( nCommand == SC_KEYMENU ) 5223 { 5224 // do not process SC_KEYMENU if we have a native menu 5225 // Windows should handle this 5226 if( GetMenu( hWnd ) ) 5227 return FALSE; 5228 5229 // Hier verarbeiten wir nur KeyMenu-Events fuer Alt um 5230 // den MenuBar zu aktivieren, oder wenn ein SysChild-Fenster 5231 // den Focus hat, da diese Alt+Tasten-Kombinationen nur 5232 // ueber diesen Event verarbeitet werden 5233 if ( !LOWORD( lParam ) ) 5234 { 5235 // Nur ausloesen, wenn keine weitere Taste gedrueckt ist. Im 5236 // Gegensatz zur Doku wird in der X-Koordinaate der CharCode 5237 // geliefert, der zusaetzlich gedrueckt ist 5238 // Also 32 fuer Space, 99 fuer c, 100 fuer d, ... 5239 // Da dies nicht dokumentiert ist, fragen wir vorsichtshalber 5240 // auch den Status der Space-Taste ab 5241 if ( GetKeyState( VK_SPACE ) & 0x8000 ) 5242 return 0; 5243 5244 // Damit nicht bei Alt+Maustaste auch der MenuBar aktiviert wird 5245 if ( (GetKeyState( VK_LBUTTON ) & 0x8000) || 5246 (GetKeyState( VK_RBUTTON ) & 0x8000) || 5247 (GetKeyState( VK_MBUTTON ) & 0x8000) || 5248 (GetKeyState( VK_SHIFT ) & 0x8000) ) 5249 return 1; 5250 5251 SalKeyEvent aKeyEvt; 5252 aKeyEvt.mnTime = GetMessageTime(); 5253 aKeyEvt.mnCode = KEY_MENU; 5254 aKeyEvt.mnCharCode = 0; 5255 aKeyEvt.mnRepeat = 0; 5256 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt ); 5257 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 5258 return (nRet != 0); 5259 } 5260 else 5261 { 5262 // Testen, ob ein SysChild den Focus hat 5263 HWND hFocusWnd = ::GetFocus(); 5264 if ( hFocusWnd && ImplFindSalObject( hFocusWnd ) ) 5265 { 5266 char cKeyCode = (char)(unsigned char)LOWORD( lParam ); 5267 // LowerCase 5268 if ( (cKeyCode >= 65) && (cKeyCode <= 90) ) 5269 cKeyCode += 32; 5270 // Wir nehmen nur 0-9 und A-Z, alle anderen Tasten muessen durch 5271 // den Hook vom SalObj verarbeitet werden 5272 if ( ((cKeyCode >= 48) && (cKeyCode <= 57)) || 5273 ((cKeyCode >= 97) && (cKeyCode <= 122)) ) 5274 { 5275 sal_uInt16 nModCode = 0; 5276 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 5277 nModCode |= KEY_SHIFT; 5278 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 5279 nModCode |= KEY_MOD1; 5280 nModCode |= KEY_MOD2; 5281 5282 SalKeyEvent aKeyEvt; 5283 aKeyEvt.mnTime = GetMessageTime(); 5284 if ( (cKeyCode >= 48) && (cKeyCode <= 57) ) 5285 aKeyEvt.mnCode = KEY_0+(cKeyCode-48); 5286 else 5287 aKeyEvt.mnCode = KEY_A+(cKeyCode-97); 5288 aKeyEvt.mnCode |= nModCode; 5289 aKeyEvt.mnCharCode = cKeyCode; 5290 aKeyEvt.mnRepeat = 0; 5291 long nRet = pFrame->CallCallback( SALEVENT_KEYINPUT, &aKeyEvt ); 5292 pFrame->CallCallback( SALEVENT_KEYUP, &aKeyEvt ); 5293 return (nRet != 0); 5294 } 5295 } 5296 } 5297 } 5298 5299 return FALSE; 5300 } 5301 5302 // ----------------------------------------------------------------------- 5303 5304 static void ImplHandleInputLangChange( HWND hWnd, WPARAM, LPARAM lParam ) 5305 { 5306 ImplSalYieldMutexAcquireWithWait(); 5307 5308 // Feststellen, ob wir IME unterstuetzen 5309 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5310 if ( pFrame && pFrame->mbIME && pFrame->mhDefIMEContext ) 5311 { 5312 HKL hKL = (HKL)lParam; 5313 UINT nImeProps = ImmGetProperty( hKL, IGP_PROPERTY ); 5314 5315 pFrame->mbSpezIME = (nImeProps & IME_PROP_SPECIAL_UI) != 0; 5316 pFrame->mbAtCursorIME = (nImeProps & IME_PROP_AT_CARET) != 0; 5317 pFrame->mbHandleIME = !pFrame->mbSpezIME; 5318 } 5319 5320 // trigger input language and codepage update 5321 UINT nLang = pFrame->mnInputLang; 5322 ImplUpdateInputLang( pFrame ); 5323 5324 // notify change 5325 if( nLang != pFrame->mnInputLang ) 5326 pFrame->CallCallback( SALEVENT_INPUTLANGUAGECHANGE, 0 ); 5327 5328 ImplSalYieldMutexRelease(); 5329 } 5330 5331 // ----------------------------------------------------------------------- 5332 5333 static void ImplUpdateIMECursorPos( WinSalFrame* pFrame, HIMC hIMC ) 5334 { 5335 COMPOSITIONFORM aForm; 5336 memset( &aForm, 0, sizeof( aForm ) ); 5337 5338 // Cursor-Position ermitteln und aus der die Default-Position fuer 5339 // das Composition-Fenster berechnen 5340 SalExtTextInputPosEvent aPosEvt; 5341 pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt ); 5342 if ( (aPosEvt.mnX == -1) && (aPosEvt.mnY == -1) ) 5343 aForm.dwStyle |= CFS_DEFAULT; 5344 else 5345 { 5346 aForm.dwStyle |= CFS_POINT; 5347 aForm.ptCurrentPos.x = aPosEvt.mnX; 5348 aForm.ptCurrentPos.y = aPosEvt.mnY; 5349 } 5350 ImmSetCompositionWindow( hIMC, &aForm ); 5351 5352 // Because not all IME's use this values, we create 5353 // a Windows caret to force the Position from the IME 5354 if ( GetFocus() == pFrame->mhWnd ) 5355 { 5356 CreateCaret( pFrame->mhWnd, 0, 5357 aPosEvt.mnWidth, aPosEvt.mnHeight ); 5358 SetCaretPos( aPosEvt.mnX, aPosEvt.mnY ); 5359 } 5360 } 5361 5362 // ----------------------------------------------------------------------- 5363 5364 static sal_Bool ImplHandleIMEStartComposition( HWND hWnd ) 5365 { 5366 sal_Bool bDef = TRUE; 5367 5368 ImplSalYieldMutexAcquireWithWait(); 5369 5370 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5371 if ( pFrame ) 5372 { 5373 HIMC hIMC = ImmGetContext( hWnd ); 5374 if ( hIMC ) 5375 { 5376 ImplUpdateIMECursorPos( pFrame, hIMC ); 5377 ImmReleaseContext( hWnd, hIMC ); 5378 } 5379 5380 if ( pFrame->mbHandleIME ) 5381 { 5382 if ( pFrame->mbAtCursorIME ) 5383 bDef = FALSE; 5384 } 5385 } 5386 5387 ImplSalYieldMutexRelease(); 5388 5389 return bDef; 5390 } 5391 5392 // ----------------------------------------------------------------------- 5393 5394 static sal_Bool ImplHandleIMECompositionInput( WinSalFrame* pFrame, 5395 HIMC hIMC, LPARAM lParam ) 5396 { 5397 sal_Bool bDef = TRUE; 5398 5399 // Init Event 5400 SalExtTextInputEvent aEvt; 5401 aEvt.mnTime = GetMessageTime(); 5402 aEvt.mpTextAttr = NULL; 5403 aEvt.mnCursorPos = 0; 5404 aEvt.mnDeltaStart = 0; 5405 aEvt.mbOnlyCursor = FALSE; 5406 aEvt.mnCursorFlags = 0; 5407 5408 // If we get a result string, then we handle this input 5409 if ( lParam & GCS_RESULTSTR ) 5410 { 5411 bDef = FALSE; 5412 5413 LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, 0, 0 ) / sizeof( WCHAR ); 5414 if ( nTextLen >= 0 ) 5415 { 5416 WCHAR* pTextBuf = new WCHAR[nTextLen]; 5417 ImmGetCompositionStringW( hIMC, GCS_RESULTSTR, pTextBuf, nTextLen*sizeof( WCHAR ) ); 5418 aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen ); 5419 delete [] pTextBuf; 5420 } 5421 5422 aEvt.mnCursorPos = aEvt.maText.Len(); 5423 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt ); 5424 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL ); 5425 ImplUpdateIMECursorPos( pFrame, hIMC ); 5426 } 5427 5428 // If the IME doesn't support OnSpot input, then there is nothing to do 5429 if ( !pFrame->mbAtCursorIME ) 5430 return !bDef; 5431 5432 // If we get new Composition data, then we handle this new input 5433 if ( (lParam & (GCS_COMPSTR | GCS_COMPATTR)) || 5434 ((lParam & GCS_CURSORPOS) && !(lParam & GCS_RESULTSTR)) ) 5435 { 5436 bDef = FALSE; 5437 5438 sal_uInt16* pSalAttrAry = NULL; 5439 LONG nTextLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ) / sizeof( WCHAR ); 5440 if ( nTextLen > 0 ) 5441 { 5442 WCHAR* pTextBuf = new WCHAR[nTextLen]; 5443 ImmGetCompositionStringW( hIMC, GCS_COMPSTR, pTextBuf, nTextLen*sizeof( WCHAR ) ); 5444 aEvt.maText = XubString( reinterpret_cast<const xub_Unicode*>(pTextBuf), (xub_StrLen)nTextLen ); 5445 delete [] pTextBuf; 5446 5447 BYTE* pAttrBuf = NULL; 5448 LONG nAttrLen = ImmGetCompositionStringW( hIMC, GCS_COMPATTR, 0, 0 ); 5449 if ( nAttrLen > 0 ) 5450 { 5451 pAttrBuf = new BYTE[nAttrLen]; 5452 ImmGetCompositionStringW( hIMC, GCS_COMPATTR, pAttrBuf, nAttrLen ); 5453 } 5454 5455 if ( pAttrBuf ) 5456 { 5457 xub_StrLen nTextLen = aEvt.maText.Len(); 5458 pSalAttrAry = new sal_uInt16[nTextLen]; 5459 memset( pSalAttrAry, 0, nTextLen*sizeof( sal_uInt16 ) ); 5460 for ( xub_StrLen i = 0; (i < nTextLen) && (i < nAttrLen); i++ ) 5461 { 5462 BYTE nWinAttr = pAttrBuf[i]; 5463 sal_uInt16 nSalAttr; 5464 if ( nWinAttr == ATTR_TARGET_CONVERTED ) 5465 { 5466 nSalAttr = SAL_EXTTEXTINPUT_ATTR_BOLDUNDERLINE; 5467 aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE; 5468 } 5469 else if ( nWinAttr == ATTR_CONVERTED ) 5470 nSalAttr = SAL_EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE; 5471 else if ( nWinAttr == ATTR_TARGET_NOTCONVERTED ) 5472 nSalAttr = SAL_EXTTEXTINPUT_ATTR_HIGHLIGHT; 5473 else if ( nWinAttr == ATTR_INPUT_ERROR ) 5474 nSalAttr = SAL_EXTTEXTINPUT_ATTR_REDTEXT | SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE; 5475 else /* ( nWinAttr == ATTR_INPUT ) */ 5476 nSalAttr = SAL_EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE; 5477 pSalAttrAry[i] = nSalAttr; 5478 } 5479 5480 aEvt.mpTextAttr = pSalAttrAry; 5481 delete [] pAttrBuf; 5482 } 5483 } 5484 5485 // Only when we get new composition data, we must send this event 5486 if ( (nTextLen > 0) || !(lParam & GCS_RESULTSTR) ) 5487 { 5488 // End the mode, if the last character is deleted 5489 if ( !nTextLen && !pFrame->mbCandidateMode ) 5490 { 5491 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt ); 5492 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL ); 5493 } 5494 else 5495 { 5496 // Because Cursor-Position and DeltaStart never updated 5497 // from the Korean input engine, we must handle this here 5498 if ( lParam & CS_INSERTCHAR ) 5499 { 5500 aEvt.mnCursorPos = nTextLen; 5501 if ( aEvt.mnCursorPos && (lParam & CS_NOMOVECARET) ) 5502 aEvt.mnCursorPos--; 5503 } 5504 else 5505 aEvt.mnCursorPos = LOWORD( ImmGetCompositionStringW( hIMC, GCS_CURSORPOS, 0, 0 ) ); 5506 5507 if ( pFrame->mbCandidateMode ) 5508 aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_INVISIBLE; 5509 if ( lParam & CS_NOMOVECARET ) 5510 aEvt.mnCursorFlags |= SAL_EXTTEXTINPUT_CURSOR_OVERWRITE; 5511 5512 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt ); 5513 } 5514 ImplUpdateIMECursorPos( pFrame, hIMC ); 5515 } 5516 5517 if ( pSalAttrAry ) 5518 delete [] pSalAttrAry; 5519 } 5520 5521 return !bDef; 5522 } 5523 5524 // ----------------------------------------------------------------------- 5525 5526 static sal_Bool ImplHandleIMEComposition( HWND hWnd, LPARAM lParam ) 5527 { 5528 sal_Bool bDef = TRUE; 5529 ImplSalYieldMutexAcquireWithWait(); 5530 5531 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5532 if ( pFrame && (!lParam || (lParam & GCS_RESULTSTR)) ) 5533 { 5534 // Wir restaurieren den Background-Modus bei jeder Texteingabe, 5535 // da einige Tools wie RichWin uns diesen hin- und wieder umsetzen 5536 if ( pFrame->mpGraphics && 5537 pFrame->mpGraphics->getHDC() ) 5538 SetBkMode( pFrame->mpGraphics->getHDC(), TRANSPARENT ); 5539 } 5540 5541 if ( pFrame && pFrame->mbHandleIME ) 5542 { 5543 if ( !lParam ) 5544 { 5545 SalExtTextInputEvent aEvt; 5546 aEvt.mnTime = GetMessageTime(); 5547 aEvt.mpTextAttr = NULL; 5548 aEvt.mnCursorPos = 0; 5549 aEvt.mnDeltaStart = 0; 5550 aEvt.mbOnlyCursor = FALSE; 5551 aEvt.mnCursorFlags = 0; 5552 pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEvt ); 5553 pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, (void*)NULL ); 5554 } 5555 else if ( lParam & (GCS_RESULTSTR | GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS) ) 5556 { 5557 HIMC hIMC = ImmGetContext( hWnd ); 5558 if ( hIMC ) 5559 { 5560 if ( ImplHandleIMECompositionInput( pFrame, hIMC, lParam ) ) 5561 bDef = FALSE; 5562 5563 ImmReleaseContext( hWnd, hIMC ); 5564 } 5565 } 5566 } 5567 5568 ImplSalYieldMutexRelease(); 5569 return bDef; 5570 } 5571 5572 // ----------------------------------------------------------------------- 5573 5574 static sal_Bool ImplHandleIMEEndComposition( HWND hWnd ) 5575 { 5576 sal_Bool bDef = TRUE; 5577 5578 ImplSalYieldMutexAcquireWithWait(); 5579 5580 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5581 if ( pFrame && pFrame->mbHandleIME ) 5582 { 5583 if ( pFrame->mbAtCursorIME ) 5584 bDef = FALSE; 5585 } 5586 5587 ImplSalYieldMutexRelease(); 5588 5589 return bDef; 5590 } 5591 5592 // ----------------------------------------------------------------------- 5593 5594 static boolean ImplHandleAppCommand( HWND hWnd, LPARAM lParam ) 5595 { 5596 sal_Int16 nCommand = 0; 5597 switch( GET_APPCOMMAND_LPARAM(lParam) ) 5598 { 5599 case APPCOMMAND_MEDIA_CHANNEL_DOWN: nCommand = MEDIA_COMMAND_CHANNEL_DOWN; break; 5600 case APPCOMMAND_MEDIA_CHANNEL_UP: nCommand = MEDIA_COMMAND_CHANNEL_UP; break; 5601 case APPCOMMAND_MEDIA_NEXTTRACK: nCommand = MEDIA_COMMAND_NEXTTRACK; break; 5602 case APPCOMMAND_MEDIA_PAUSE: nCommand = MEDIA_COMMAND_PAUSE; break; 5603 case APPCOMMAND_MEDIA_PLAY: nCommand = MEDIA_COMMAND_PLAY; break; 5604 case APPCOMMAND_MEDIA_PLAY_PAUSE: nCommand = MEDIA_COMMAND_PLAY_PAUSE; break; 5605 case APPCOMMAND_MEDIA_PREVIOUSTRACK: nCommand = MEDIA_COMMAND_PREVIOUSTRACK; break; 5606 case APPCOMMAND_MEDIA_RECORD: nCommand = MEDIA_COMMAND_RECORD; break; 5607 case APPCOMMAND_MEDIA_REWIND: nCommand = MEDIA_COMMAND_REWIND; break; 5608 case APPCOMMAND_MEDIA_STOP: nCommand = MEDIA_COMMAND_STOP; break; 5609 case APPCOMMAND_MIC_ON_OFF_TOGGLE: nCommand = MEDIA_COMMAND_MIC_ON_OFF_TOGGLE; break; 5610 case APPCOMMAND_MICROPHONE_VOLUME_DOWN: nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_DOWN; break; 5611 case APPCOMMAND_MICROPHONE_VOLUME_MUTE: nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_MUTE; break; 5612 case APPCOMMAND_MICROPHONE_VOLUME_UP: nCommand = MEDIA_COMMAND_MICROPHONE_VOLUME_UP; break; 5613 case APPCOMMAND_VOLUME_DOWN: nCommand = MEDIA_COMMAND_VOLUME_DOWN; break; 5614 case APPCOMMAND_VOLUME_MUTE: nCommand = MEDIA_COMMAND_VOLUME_MUTE; break; 5615 case APPCOMMAND_VOLUME_UP: nCommand = MEDIA_COMMAND_VOLUME_UP; break; 5616 break; 5617 default: 5618 return false; 5619 } 5620 5621 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5622 Window *pWindow = pFrame ? pFrame->GetWindow() : NULL; 5623 5624 if( pWindow ) 5625 { 5626 const Point aPoint; 5627 CommandEvent aCEvt( aPoint, COMMAND_MEDIA, FALSE, &nCommand ); 5628 NotifyEvent aNCmdEvt( EVENT_COMMAND, pWindow, &aCEvt ); 5629 5630 if ( !ImplCallPreNotify( aNCmdEvt ) ) 5631 { 5632 pWindow->Command( aCEvt ); 5633 return true; 5634 } 5635 } 5636 5637 return false; 5638 } 5639 5640 5641 static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam ) 5642 { 5643 if ( wParam == (WPARAM)IMN_OPENCANDIDATE ) 5644 { 5645 ImplSalYieldMutexAcquireWithWait(); 5646 5647 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5648 if ( pFrame && pFrame->mbHandleIME && 5649 pFrame->mbAtCursorIME ) 5650 { 5651 // Wir wollen den Cursor hiden 5652 pFrame->mbCandidateMode = TRUE; 5653 ImplHandleIMEComposition( hWnd, GCS_CURSORPOS ); 5654 5655 HWND hWnd = pFrame->mhWnd; 5656 HIMC hIMC = ImmGetContext( hWnd ); 5657 if ( hIMC ) 5658 { 5659 LONG nBufLen = ImmGetCompositionStringW( hIMC, GCS_COMPSTR, 0, 0 ); 5660 if ( nBufLen >= 1 ) 5661 { 5662 SalExtTextInputPosEvent aPosEvt; 5663 pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvt ); 5664 5665 // Vertical !!! 5666 CANDIDATEFORM aForm; 5667 aForm.dwIndex = 0; 5668 aForm.dwStyle = CFS_EXCLUDE; 5669 aForm.ptCurrentPos.x = aPosEvt.mnX; 5670 aForm.ptCurrentPos.y = aPosEvt.mnY+1; 5671 aForm.rcArea.left = aPosEvt.mnX; 5672 aForm.rcArea.top = aPosEvt.mnY; 5673 aForm.rcArea.right = aForm.rcArea.left+aPosEvt.mnExtWidth+1; 5674 aForm.rcArea.bottom = aForm.rcArea.top+aPosEvt.mnHeight+1; 5675 ImmSetCandidateWindow( hIMC, &aForm ); 5676 } 5677 5678 ImmReleaseContext( hWnd, hIMC ); 5679 } 5680 } 5681 5682 ImplSalYieldMutexRelease(); 5683 } 5684 else if ( wParam == (WPARAM)IMN_CLOSECANDIDATE ) 5685 { 5686 ImplSalYieldMutexAcquireWithWait(); 5687 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5688 if ( pFrame ) 5689 pFrame->mbCandidateMode = FALSE; 5690 ImplSalYieldMutexRelease(); 5691 } 5692 } 5693 5694 // ----------------------------------------------------------------------- 5695 #if WINVER >= 0x0500 5696 5697 static LRESULT ImplHandleIMEReconvertString( HWND hWnd, LPARAM lParam ) 5698 { 5699 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5700 LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam; 5701 LRESULT nRet = 0; 5702 SalSurroundingTextRequestEvent aEvt; 5703 aEvt.maText = UniString(); 5704 aEvt.mnStart = aEvt.mnEnd = 0; 5705 5706 UINT nImeProps = ImmGetProperty( GetKeyboardLayout( 0 ), IGP_SETCOMPSTR ); 5707 if( (nImeProps & SCS_CAP_SETRECONVERTSTRING) == 0 ) 5708 { 5709 // This IME does not support reconversion. 5710 return 0; 5711 } 5712 5713 if( !pReconvertString ) 5714 { 5715 // The first call for reconversion. 5716 pFrame->CallCallback( SALEVENT_STARTRECONVERSION, (void*)NULL ); 5717 5718 // Retrieve the surrounding text from the focused control. 5719 pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt ); 5720 5721 if( aEvt.maText.Len() == 0 ) 5722 { 5723 return 0; 5724 } 5725 5726 nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR); 5727 } 5728 else 5729 { 5730 // The second call for reconversion. 5731 5732 // Retrieve the surrounding text from the focused control. 5733 pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt ); 5734 nRet = sizeof(RECONVERTSTRING) + (aEvt.maText.Len() + 1) * sizeof(WCHAR); 5735 5736 pReconvertString->dwStrOffset = sizeof(RECONVERTSTRING); 5737 pReconvertString->dwStrLen = aEvt.maText.Len(); 5738 pReconvertString->dwCompStrOffset = aEvt.mnStart * sizeof(WCHAR); 5739 pReconvertString->dwCompStrLen = aEvt.mnEnd - aEvt.mnStart; 5740 pReconvertString->dwTargetStrOffset = pReconvertString->dwCompStrOffset; 5741 pReconvertString->dwTargetStrLen = pReconvertString->dwCompStrLen; 5742 5743 memcpy( (LPWSTR)(pReconvertString + 1), aEvt.maText.GetBuffer(), (aEvt.maText.Len() + 1) * sizeof(WCHAR) ); 5744 } 5745 5746 // just return the required size of buffer to reconvert. 5747 return nRet; 5748 } 5749 5750 // ----------------------------------------------------------------------- 5751 5752 static LRESULT ImplHandleIMEConfirmReconvertString( HWND hWnd, LPARAM lParam ) 5753 { 5754 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 5755 LPRECONVERTSTRING pReconvertString = (LPRECONVERTSTRING) lParam; 5756 SalSurroundingTextRequestEvent aEvt; 5757 aEvt.maText = UniString(); 5758 aEvt.mnStart = aEvt.mnEnd = 0; 5759 5760 pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTREQUEST, (void*)&aEvt ); 5761 5762 sal_uLong nTmpStart = pReconvertString->dwCompStrOffset / sizeof(WCHAR); 5763 sal_uLong nTmpEnd = nTmpStart + pReconvertString->dwCompStrLen; 5764 5765 if( nTmpStart != aEvt.mnStart || nTmpEnd != aEvt.mnEnd ) 5766 { 5767 SalSurroundingTextSelectionChangeEvent aSelEvt; 5768 aSelEvt.mnStart = nTmpStart; 5769 aSelEvt.mnEnd = nTmpEnd; 5770 5771 pFrame->CallCallback( SALEVENT_SURROUNDINGTEXTSELECTIONCHANGE, (void*)&aSelEvt ); 5772 } 5773 5774 return TRUE; 5775 } 5776 5777 #endif // WINVER >= 0x0500 5778 5779 // ----------------------------------------------------------------------- 5780 5781 void SalTestMouseLeave() 5782 { 5783 SalData* pSalData = GetSalData(); 5784 5785 if ( pSalData->mhWantLeaveMsg && !::GetCapture() ) 5786 { 5787 POINT aPt; 5788 GetCursorPos( &aPt ); 5789 if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) ) 5790 ImplSendMessage( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) ); 5791 } 5792 } 5793 5794 // ----------------------------------------------------------------------- 5795 5796 static int ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam , 5797 LRESULT& rResult ) 5798 { 5799 POINT aPt; 5800 POINT aScreenPt; 5801 aScreenPt.x = (short)LOWORD( lParam ); 5802 aScreenPt.y = (short)HIWORD( lParam ); 5803 // Child-Fenster suchen, welches an der entsprechenden 5804 // Position liegt 5805 HWND hChildWnd; 5806 HWND hWheelWnd = hWnd; 5807 do 5808 { 5809 hChildWnd = hWheelWnd; 5810 aPt = aScreenPt; 5811 ScreenToClient( hChildWnd, &aPt ); 5812 hWheelWnd = ChildWindowFromPointEx( hChildWnd, aPt, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT ); 5813 } 5814 while ( hWheelWnd && (hWheelWnd != hChildWnd) ); 5815 if ( hWheelWnd && (hWheelWnd != hWnd) && 5816 (hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) ) 5817 { 5818 rResult = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam ); 5819 return FALSE; 5820 } 5821 5822 return TRUE; 5823 } 5824 5825 // ----------------------------------------------------------------------- 5826 5827 LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ) 5828 { 5829 LRESULT nRet = 0; 5830 static int bInWheelMsg = FALSE; 5831 static int bInQueryEnd = FALSE; 5832 5833 // By WM_CREATE we connect the frame with the window handle 5834 if ( nMsg == WM_CREATE ) 5835 { 5836 // Window-Instanz am Windowhandle speichern 5837 // Can also be used for the W-Version, because the struct 5838 // to access lpCreateParams is the same structure 5839 CREATESTRUCTA* pStruct = (CREATESTRUCTA*)lParam; 5840 WinSalFrame* pFrame = (WinSalFrame*)pStruct->lpCreateParams; 5841 if ( pFrame != 0 ) 5842 { 5843 SetWindowPtr( hWnd, pFrame ); 5844 // HWND schon hier setzen, da schon auf den Instanzdaten 5845 // gearbeitet werden kann, wenn Messages waehrend 5846 // CreateWindow() gesendet werden 5847 pFrame->mhWnd = hWnd; 5848 pFrame->maSysData.hWnd = hWnd; 5849 } 5850 return 0; 5851 } 5852 5853 ImplSVData* pSVData = ImplGetSVData(); 5854 // #i72707# TODO: the mbDeInit check will not be needed 5855 // once all windows that are not properly closed on exit got fixed 5856 if( pSVData->mbDeInit ) 5857 return 0; 5858 5859 if ( WM_USER_SYSTEM_WINDOW_ACTIVATED == nMsg ) 5860 { 5861 if (pSVData->mpIntroWindow) 5862 pSVData->mpIntroWindow->Hide(); 5863 5864 return 0; 5865 } 5866 5867 bool bCheckTimers = false; 5868 5869 switch( nMsg ) 5870 { 5871 case WM_MOUSEMOVE: 5872 case WM_LBUTTONDOWN: 5873 case WM_MBUTTONDOWN: 5874 case WM_RBUTTONDOWN: 5875 case WM_LBUTTONUP: 5876 case WM_MBUTTONUP: 5877 case WM_RBUTTONUP: 5878 case WM_NCMOUSEMOVE: 5879 case SAL_MSG_MOUSELEAVE: 5880 ImplSalYieldMutexAcquireWithWait(); 5881 rDef = !ImplHandleMouseMsg( hWnd, nMsg, wParam, lParam ); 5882 ImplSalYieldMutexRelease(); 5883 break; 5884 5885 case WM_NCLBUTTONDOWN: 5886 case WM_NCMBUTTONDOWN: 5887 case WM_NCRBUTTONDOWN: 5888 ImplSalYieldMutexAcquireWithWait(); 5889 ImplCallClosePopupsHdl( hWnd ); // close popups... 5890 ImplSalYieldMutexRelease(); 5891 break; 5892 5893 case WM_MOUSEACTIVATE: 5894 if ( LOWORD( lParam ) == HTCLIENT ) 5895 { 5896 ImplSalYieldMutexAcquireWithWait(); 5897 nRet = ImplHandleMouseActivateMsg( hWnd ); 5898 ImplSalYieldMutexRelease(); 5899 if ( nRet ) 5900 { 5901 nRet = MA_NOACTIVATE; 5902 rDef = FALSE; 5903 } 5904 } 5905 break; 5906 5907 case WM_KEYDOWN: 5908 case WM_KEYUP: 5909 case WM_DEADCHAR: 5910 case WM_CHAR: 5911 case WM_UNICHAR: // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0 5912 case WM_SYSKEYDOWN: 5913 case WM_SYSKEYUP: 5914 case WM_SYSCHAR: 5915 ImplSalYieldMutexAcquireWithWait(); 5916 rDef = !ImplHandleKeyMsg( hWnd, nMsg, wParam, lParam, nRet ); 5917 ImplSalYieldMutexRelease(); 5918 break; 5919 5920 case WM_MOUSEWHEEL: 5921 // FALLTHROUGH intended 5922 case WM_MOUSEHWHEEL: 5923 // Gegen Rekursion absichern, falls wir vom IE oder dem externen 5924 // Fenster die Message wieder zurueckbekommen 5925 if ( !bInWheelMsg ) 5926 { 5927 bInWheelMsg++; 5928 rDef = !ImplHandleWheelMsg( hWnd, nMsg, wParam, lParam ); 5929 // Wenn wir die Message nicht ausgewertet haben, schauen wir 5930 // noch einmal nach, ob dort ein geplugtes Fenster steht, 5931 // welches wir dann benachrichtigen 5932 if ( rDef ) 5933 rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet ); 5934 bInWheelMsg--; 5935 } 5936 break; 5937 5938 case WM_COMMAND: 5939 ImplSalYieldMutexAcquireWithWait(); 5940 rDef = !ImplHandleCommand( hWnd, wParam, lParam ); 5941 ImplSalYieldMutexRelease(); 5942 break; 5943 5944 case WM_INITMENUPOPUP: 5945 ImplSalYieldMutexAcquireWithWait(); 5946 rDef = !ImplHandleMenuActivate( hWnd, wParam, lParam ); 5947 ImplSalYieldMutexRelease(); 5948 break; 5949 5950 case WM_MENUSELECT: 5951 ImplSalYieldMutexAcquireWithWait(); 5952 rDef = !ImplHandleMenuSelect( hWnd, wParam, lParam ); 5953 ImplSalYieldMutexRelease(); 5954 break; 5955 5956 case WM_SYSCOMMAND: 5957 ImplSalYieldMutexAcquireWithWait(); 5958 nRet = ImplHandleSysCommand( hWnd, wParam, lParam ); 5959 ImplSalYieldMutexRelease(); 5960 if ( nRet ) 5961 rDef = FALSE; 5962 break; 5963 5964 case WM_MENUCHAR: 5965 nRet = ImplMenuChar( hWnd, wParam, lParam ); 5966 if( nRet ) 5967 rDef = FALSE; 5968 break; 5969 5970 case WM_MEASUREITEM: 5971 nRet = ImplMeasureItem(hWnd, wParam, lParam); 5972 if( nRet ) 5973 rDef = FALSE; 5974 break; 5975 5976 case WM_DRAWITEM: 5977 nRet = ImplDrawItem(hWnd, wParam, lParam); 5978 if( nRet ) 5979 rDef = FALSE; 5980 break; 5981 5982 case WM_MOVE: 5983 case SAL_MSG_POSTMOVE: 5984 ImplHandleMoveMsg( hWnd ); 5985 rDef = FALSE; 5986 break; 5987 case WM_SIZE: 5988 ImplHandleSizeMsg( hWnd, wParam, lParam ); 5989 rDef = FALSE; 5990 break; 5991 case SAL_MSG_POSTCALLSIZE: 5992 ImplCallSizeHdl( hWnd ); 5993 rDef = FALSE; 5994 break; 5995 5996 case WM_GETMINMAXINFO: 5997 if ( ImplHandleMinMax( hWnd, lParam ) ) 5998 rDef = FALSE; 5999 break; 6000 6001 case WM_ERASEBKGND: 6002 nRet = 1; 6003 rDef = FALSE; 6004 break; 6005 case WM_PAINT: 6006 bCheckTimers = ImplHandlePaintMsg( hWnd ); 6007 rDef = FALSE; 6008 break; 6009 case SAL_MSG_POSTPAINT: 6010 ImplHandlePaintMsg2( hWnd, (RECT*)wParam ); 6011 bCheckTimers = true; 6012 rDef = FALSE; 6013 break; 6014 6015 case SAL_MSG_FORCEPALETTE: 6016 ImplHandleForcePalette( hWnd ); 6017 rDef = FALSE; 6018 break; 6019 6020 case WM_QUERYNEWPALETTE: 6021 case SAL_MSG_POSTQUERYNEWPAL: 6022 nRet = ImplHandlePalette( TRUE, hWnd, nMsg, wParam, lParam, rDef ); 6023 break; 6024 6025 case WM_ACTIVATE: 6026 // Wenn wir aktiviert werden, dann wollen wir auch unsere 6027 // Palette setzen. Wir machen dieses in Activate, 6028 // damit andere externe Child-Fenster auch unsere Palette 6029 // ueberschreiben koennen. So wird unsere jedenfalls nur einmal 6030 // gesetzt und nicht immer rekursiv, da an allen anderen Stellen 6031 // diese nur als Background-Palette gesetzt wird 6032 if ( LOWORD( wParam ) != WA_INACTIVE ) 6033 ImplSendMessage( hWnd, SAL_MSG_FORCEPALETTE, 0, 0 ); 6034 break; 6035 6036 case WM_ENABLE: 6037 // #95133# a system dialog is opened/closed, using our app window as parent 6038 { 6039 WinSalFrame* pFrame = GetWindowPtr( hWnd ); 6040 Window *pWin = NULL; 6041 if( pFrame ) 6042 pWin = pFrame->GetWindow(); 6043 6044 if( !wParam ) 6045 { 6046 ImplSVData* pSVData = ImplGetSVData(); 6047 pSVData->maAppData.mnModalMode++; 6048 6049 // #106431#, hide SplashScreen 6050 if( pSVData->mpIntroWindow ) 6051 pSVData->mpIntroWindow->Hide(); 6052 6053 if( pWin ) 6054 { 6055 pWin->EnableInput( FALSE, TRUE, TRUE, NULL ); 6056 pWin->ImplIncModalCount(); // #106303# support frame based modal count 6057 } 6058 } 6059 else 6060 { 6061 ImplGetSVData()->maAppData.mnModalMode--; 6062 if( pWin ) 6063 { 6064 pWin->EnableInput( TRUE, TRUE, TRUE, NULL ); 6065 pWin->ImplDecModalCount(); // #106303# support frame based modal count 6066 } 6067 } 6068 } 6069 break; 6070 6071 case WM_KILLFOCUS: 6072 DestroyCaret(); 6073 case WM_SETFOCUS: 6074 case SAL_MSG_POSTFOCUS: 6075 ImplHandleFocusMsg( hWnd ); 6076 rDef = FALSE; 6077 break; 6078 6079 case WM_CLOSE: 6080 ImplHandleCloseMsg( hWnd ); 6081 rDef = FALSE; 6082 break; 6083 6084 case WM_QUERYENDSESSION: 6085 if( !bInQueryEnd ) 6086 { 6087 // handle queryendsession only once 6088 bInQueryEnd = TRUE; 6089 nRet = !ImplHandleShutDownMsg( hWnd ); 6090 rDef = FALSE; 6091 6092 // Issue #16314#: ImplHandleShutDownMsg causes a PostMessage in case of allowing shutdown. 6093 // This posted message was never processed and cause Windows XP to hang after log off 6094 // if there are multiple sessions and the current session wasn't the first one started. 6095 // So if shutdown is allowed we assume that a post message was done and retrieve all 6096 // messages in the message queue and dispatch them before we return control to the system. 6097 6098 if ( nRet ) 6099 { 6100 MSG msg; 6101 6102 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) 6103 { 6104 DispatchMessage( &msg ); 6105 } 6106 } 6107 } 6108 else 6109 { 6110 ImplSalYieldMutexAcquireWithWait(); 6111 ImplSalYieldMutexRelease(); 6112 rDef = TRUE; 6113 } 6114 break; 6115 6116 case WM_ENDSESSION: 6117 if( !wParam ) 6118 bInQueryEnd = FALSE; // no shutdown: allow query again 6119 nRet = FALSE; 6120 rDef = FALSE; 6121 break; 6122 6123 case WM_DISPLAYCHANGE: 6124 case WM_SETTINGCHANGE: 6125 case WM_DEVMODECHANGE: 6126 case WM_FONTCHANGE: 6127 case WM_SYSCOLORCHANGE: 6128 case WM_TIMECHANGE: 6129 ImplHandleSettingsChangeMsg( hWnd, nMsg, wParam, lParam ); 6130 break; 6131 6132 case WM_THEMECHANGED: 6133 GetSalData()->mbThemeChanged = TRUE; 6134 break; 6135 6136 case SAL_MSG_USEREVENT: 6137 ImplHandleUserEvent( hWnd, lParam ); 6138 rDef = FALSE; 6139 break; 6140 6141 case SAL_MSG_CAPTUREMOUSE: 6142 SetCapture( hWnd ); 6143 rDef = FALSE; 6144 break; 6145 case SAL_MSG_RELEASEMOUSE: 6146 if ( ::GetCapture() == hWnd ) 6147 ReleaseCapture(); 6148 rDef = FALSE; 6149 break; 6150 case SAL_MSG_TOTOP: 6151 ImplSalToTop( hWnd, (sal_uInt16)wParam ); 6152 rDef = FALSE; 6153 break; 6154 case SAL_MSG_SHOW: 6155 ImplSalShow( hWnd, (sal_Bool)wParam, (sal_Bool)lParam ); 6156 rDef = FALSE; 6157 break; 6158 case SAL_MSG_SETINPUTCONTEXT: 6159 ImplSalFrameSetInputContext( hWnd, (const SalInputContext*)(void*)lParam ); 6160 rDef = FALSE; 6161 break; 6162 case SAL_MSG_ENDEXTTEXTINPUT: 6163 ImplSalFrameEndExtTextInput( hWnd, (sal_uInt16)(sal_uLong)(void*)wParam ); 6164 rDef = FALSE; 6165 break; 6166 6167 case WM_INPUTLANGCHANGE: 6168 ImplHandleInputLangChange( hWnd, wParam, lParam ); 6169 break; 6170 6171 case WM_IME_CHAR: 6172 // #103487#, some IMEs (e.g. those that do not work onspot) 6173 // may send WM_IME_CHAR instead of WM_IME_COMPOSITION 6174 // we just handle it like a WM_CHAR message - seems to work fine 6175 ImplSalYieldMutexAcquireWithWait(); 6176 rDef = !ImplHandleKeyMsg( hWnd, WM_CHAR, wParam, lParam, nRet ); 6177 ImplSalYieldMutexRelease(); 6178 break; 6179 6180 case WM_IME_STARTCOMPOSITION: 6181 rDef = ImplHandleIMEStartComposition( hWnd ); 6182 break; 6183 6184 case WM_IME_COMPOSITION: 6185 rDef = ImplHandleIMEComposition( hWnd, lParam ); 6186 break; 6187 6188 case WM_IME_ENDCOMPOSITION: 6189 rDef = ImplHandleIMEEndComposition( hWnd ); 6190 break; 6191 6192 case WM_IME_NOTIFY: 6193 ImplHandleIMENotify( hWnd, wParam ); 6194 break; 6195 6196 #ifdef WNT 6197 case WM_GETOBJECT: 6198 { 6199 if (!Application::IsEnableAccessInterface()) 6200 { 6201 break; 6202 } 6203 else 6204 { 6205 // IA2 should be enabled automatically 6206 AllSettings aSettings = Application::GetSettings(); 6207 MiscSettings aMisc = aSettings.GetMiscSettings(); 6208 aMisc.SetEnableATToolSupport( sal_True ); 6209 aSettings.SetMiscSettings( aMisc ); 6210 Application::SetSettings( aSettings ); 6211 6212 if (Application::GetSettings().GetMiscSettings().GetEnableATToolSupport()) 6213 { 6214 // Make sure to launch Accessibility only the following criteria are satisfied to avoid RFT interrupts regular acc processing 6215 if (g_acc_manager1 == NULL) 6216 { 6217 sal_Bool bCancelled(sal_False); 6218 InitAccessBridge(sal_False,bCancelled); 6219 if( bCancelled ) 6220 break; 6221 } 6222 if (g_acc_manager1 != NULL) 6223 { 6224 // MT: mhOnSetTitleWnd not set to reasonable value anywhere... 6225 /* 6226 sal_Bool bSkipSetTitleClient = sal_False; 6227 SalFrame* pFrame = GetWindowPtr( hWnd ); 6228 if(pFrame) 6229 { 6230 bSkipSetTitleClient = (lParam == OBJID_CLIENT && hWnd == ((WinSalFrame*)pFrame)->mhOnSetTitleWnd); 6231 } 6232 */ 6233 if ( (lParam == OBJID_CLIENT ) /* && !bSkipSetTitleClient */ ) 6234 { 6235 long RetResult = g_acc_manager1->getAccObjectPtr((long)hWnd, lParam, wParam); 6236 if(RetResult != 0) 6237 { 6238 rDef = FALSE; 6239 return (HRESULT)RetResult; 6240 } 6241 } 6242 } 6243 } 6244 } 6245 break; 6246 } 6247 #endif 6248 6249 case WM_APPCOMMAND: 6250 if( ImplHandleAppCommand( hWnd, lParam ) ) 6251 { 6252 rDef = false; 6253 nRet = 1; 6254 } 6255 break; 6256 #if WINVER >= 0x0500 6257 case WM_IME_REQUEST: 6258 if ( PtrToInt( wParam ) == IMR_RECONVERTSTRING ) 6259 { 6260 nRet = ImplHandleIMEReconvertString( hWnd, lParam ); 6261 rDef = FALSE; 6262 } 6263 else if( PtrToInt( wParam ) == IMR_CONFIRMRECONVERTSTRING ) 6264 { 6265 nRet = ImplHandleIMEConfirmReconvertString( hWnd, lParam ); 6266 rDef = FALSE; 6267 } 6268 break; 6269 #endif // WINVER >= 0x0500 6270 } 6271 6272 // WheelMouse-Message abfangen 6273 if ( rDef && (nMsg == aSalShlData.mnWheelMsgId) && aSalShlData.mnWheelMsgId ) 6274 { 6275 // Gegen Rekursion absichern, falls wir vom IE oder dem externen 6276 // Fenster die Message wieder zurueckbekommen 6277 if ( !bInWheelMsg ) 6278 { 6279 bInWheelMsg++; 6280 // Zuerst wollen wir die Message dispatchen und dann darf auch 6281 // das SystemWindow drankommen 6282 WORD nKeyState = 0; 6283 if ( GetKeyState( VK_SHIFT ) & 0x8000 ) 6284 nKeyState |= MK_SHIFT; 6285 if ( GetKeyState( VK_CONTROL ) & 0x8000 ) 6286 nKeyState |= MK_CONTROL; 6287 // Mutex handling is inside from this call 6288 rDef = !ImplHandleWheelMsg( hWnd, 6289 WM_MOUSEWHEEL, 6290 MAKEWPARAM( nKeyState, (WORD)wParam ), 6291 lParam ); 6292 if ( rDef ) 6293 { 6294 HWND hWheelWnd = ::GetFocus(); 6295 if ( hWheelWnd && (hWheelWnd != hWnd) ) 6296 { 6297 nRet = ImplSendMessage( hWheelWnd, nMsg, wParam, lParam ); 6298 rDef = FALSE; 6299 } 6300 else 6301 rDef = ImplSalWheelMousePos( hWnd, nMsg, wParam, lParam, nRet ); 6302 } 6303 bInWheelMsg--; 6304 } 6305 } 6306 6307 if( bCheckTimers ) 6308 { 6309 SalData* pSalData = GetSalData(); 6310 if( pSalData->mnNextTimerTime ) 6311 { 6312 DWORD nCurTime = GetTickCount(); 6313 if( pSalData->mnNextTimerTime < nCurTime ) 6314 { 6315 MSG aMsg; 6316 if( ! ImplPeekMessage( &aMsg, 0, WM_PAINT, WM_PAINT, PM_NOREMOVE | PM_NOYIELD ) ) 6317 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_POSTTIMER, 0, nCurTime ); 6318 } 6319 } 6320 } 6321 6322 return nRet; 6323 } 6324 6325 LRESULT CALLBACK SalFrameWndProcA( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) 6326 { 6327 int bDef = TRUE; 6328 LRESULT nRet = 0; 6329 #ifdef __MINGW32__ 6330 jmp_buf jmpbuf; 6331 __SEHandler han; 6332 if (__builtin_setjmp(jmpbuf) == 0) 6333 { 6334 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 6335 #else 6336 __try 6337 { 6338 #endif 6339 nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef ); 6340 } 6341 #ifdef __MINGW32__ 6342 han.Reset(); 6343 #else 6344 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation())) 6345 { 6346 } 6347 #endif 6348 if ( bDef ) 6349 nRet = DefWindowProcA( hWnd, nMsg, wParam, lParam ); 6350 return nRet; 6351 } 6352 6353 LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) 6354 { 6355 int bDef = TRUE; 6356 LRESULT nRet = 0; 6357 #ifdef __MINGW32__ 6358 jmp_buf jmpbuf; 6359 __SEHandler han; 6360 if (__builtin_setjmp(jmpbuf) == 0) 6361 { 6362 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER); 6363 #else 6364 __try 6365 { 6366 #endif 6367 nRet = SalFrameWndProc( hWnd, nMsg, wParam, lParam, bDef ); 6368 } 6369 #ifdef __MINGW32__ 6370 han.Reset(); 6371 #else 6372 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation())) 6373 { 6374 } 6375 #endif 6376 6377 if ( bDef ) 6378 nRet = DefWindowProcW( hWnd, nMsg, wParam, lParam ); 6379 return nRet; 6380 } 6381 6382 // ----------------------------------------------------------------------- 6383 6384 sal_Bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult ) 6385 { 6386 // handle all messages concerning all frames so they get processed only once 6387 // Must work for Unicode and none Unicode 6388 sal_Bool bResult = FALSE; 6389 if ( (nMsg == WM_PALETTECHANGED) || (nMsg == SAL_MSG_POSTPALCHANGED) ) 6390 { 6391 int bDef = TRUE; 6392 rlResult = ImplHandlePalette( FALSE, hWnd, nMsg, wParam, lParam, bDef ); 6393 bResult = (bDef != 0); 6394 } 6395 else if( nMsg == WM_DISPLAYCHANGE ) 6396 { 6397 WinSalSystem* pSys = static_cast<WinSalSystem*>(ImplGetSalSystem()); 6398 if( pSys ) 6399 pSys->clearMonitors(); 6400 bResult = (pSys != NULL); 6401 } 6402 return bResult; 6403 } 6404 6405 // ----------------------------------------------------------------------- 6406 6407 sal_Bool ImplWriteLastError( DWORD lastError, const char *szApiCall ) 6408 { 6409 static int first=1; 6410 // if VCL_LOGFILE_ENABLED is set, Win32 API error messages can be written 6411 // to %TMP%/vcl.log or %TEMP%/vcl.log 6412 static char *logEnabled = getenv("VCL_LOGFILE_ENABLED"); 6413 if( logEnabled ) 6414 { 6415 sal_Bool bSuccess = FALSE; 6416 static char *szTmp = getenv("TMP"); 6417 if( !szTmp || !*szTmp ) 6418 szTmp = getenv("TEMP"); 6419 if( szTmp && *szTmp ) 6420 { 6421 char fname[5000]; 6422 strcpy( fname, szTmp ); 6423 if( fname[strlen(fname) - 1] != '\\' ) 6424 strcat( fname, "\\"); 6425 strcat( fname, "vcl.log" ); 6426 FILE *fp = fopen( fname, "a" ); // always append 6427 if( fp ) 6428 { 6429 if( first ) 6430 { 6431 first = 0; 6432 fprintf( fp, "Process ID: %d (0x%x)\n", GetCurrentProcessId(), GetCurrentProcessId() ); 6433 } 6434 time_t aclock; 6435 time( &aclock ); // Get time in seconds 6436 struct tm *newtime = localtime( &aclock ); // Convert time to struct tm form 6437 fprintf( fp, asctime( newtime ) ); // print time stamp 6438 6439 fprintf( fp, "%s returned %u (0x%x)\n", szApiCall, lastError, lastError ); 6440 bSuccess = TRUE; // may be FormatMessage fails but we wrote at least the error code 6441 6442 LPVOID lpMsgBuf; 6443 if (FormatMessageA( 6444 FORMAT_MESSAGE_ALLOCATE_BUFFER | 6445 FORMAT_MESSAGE_FROM_SYSTEM | 6446 FORMAT_MESSAGE_IGNORE_INSERTS, 6447 NULL, 6448 lastError, 6449 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 6450 (LPSTR) &lpMsgBuf, 6451 0, 6452 NULL )) 6453 { 6454 fprintf( fp, " %s\n", (LPSTR)lpMsgBuf ); 6455 LocalFree( lpMsgBuf ); 6456 } 6457 6458 fclose( fp ); 6459 } 6460 } 6461 return bSuccess; 6462 } 6463 else 6464 return TRUE; 6465 } 6466 6467 // ----------------------------------------------------------------------- 6468 6469 #ifdef WNT 6470 bool IsWNTInitAccessBridge() 6471 { 6472 return NULL != g_acc_manager1; 6473 } 6474 #endif 6475 #ifdef WNT 6476 bool WNTEnableAccessInterface(bool bEnable) 6477 { 6478 ImplSVData* pSVData = ImplGetSVData(); 6479 6480 BOOL bPreVal = pSVData->maAppData.m_bEnableAccessInterface; 6481 long nEnable= bEnable; 6482 ::InterlockedExchange( 6483 (LPLONG)&(pSVData->maAppData.m_bEnableAccessInterface), 6484 nEnable); 6485 6486 return bPreVal; 6487 } 6488 #endif 6489