BITMAPINFO * image_get_binfo( Handle self, XBITMAPINFO * bi) { int i; PImage image = ( PImage) self; int nColors; int bitCount, lower; if ( is_apt( aptDeviceBitmap)) { memcpy( bi, &guts. displayBMInfo, sizeof( BITMAPINFO)); if ((( PDeviceBitmap) self)-> monochrome) { bi-> bmiHeader. biPlanes = bi-> bmiHeader. biBitCount = 1; bi-> bmiHeader. biClrUsed = bi-> bmiHeader. biClrImportant = 2; } else if ( bi-> bmiHeader. biBitCount <= 8) { nColors = 1 << ( bi-> bmiHeader. biBitCount * bi-> bmiHeader. biPlanes); if ( sys pal) { GetPaletteEntries( sys pal, 0, nColors, ( LPPALETTEENTRY) &bi-> bmiColors); bi-> bmiHeader. biClrUsed = bi-> bmiHeader. biClrImportant = nColors; } else bi-> bmiHeader. biClrUsed = bi-> bmiHeader. biClrImportant = 0; } else bi-> bmiHeader. biClrUsed = bi-> bmiHeader. biClrImportant = 0; return ( BITMAPINFO *) bi; } if ( image_screenable( self, nilHandle, &lower)) { nColors = (( 1 << ( image-> type & imBPP)) & 0x1ff); bitCount = image-> type & imBPP; } else { nColors = ( 1 << lower) & 0x1ff; bitCount = lower; } if ( nColors > image-> palSize) nColors = image-> palSize; memset( bi, 0, sizeof( BITMAPINFOHEADER) + nColors * sizeof( RGBQUAD)); bi-> bmiHeader. biSize = sizeof( BITMAPINFOHEADER); // - sizeof( RGBQUAD); bi-> bmiHeader. biWidth = image-> w; bi-> bmiHeader. biHeight = image-> h; bi-> bmiHeader. biPlanes = 1; bi-> bmiHeader. biBitCount = bitCount; bi-> bmiHeader. biCompression = BI_RGB; bi-> bmiHeader. biClrUsed = nColors; bi-> bmiHeader. biClrImportant = nColors; for ( i = 0; i < nColors; i++) { bi-> bmiColors[ i]. rgbRed = image-> palette[ i]. r; bi-> bmiColors[ i]. rgbGreen = image-> palette[ i]. g; bi-> bmiColors[ i]. rgbBlue = image-> palette[ i]. b; } return ( BITMAPINFO *) bi; }
Bool image_set_cache( Handle from, Handle self) { if ( sys pal == nil) sys pal = image_make_bitmap_palette( from); if ( sys bm == nil) { sys bm = image_make_bitmap_handle( from, sys pal); if ( sys bm == nil) return false; if ( !is_apt( aptDeviceBitmap)) hash_store( imageMan, &self, sizeof( self), (void*)self); } return true; }
LRESULT CALLBACK generic_view_handler( HWND win, UINT msg, WPARAM mp1, LPARAM mp2) { LRESULT ret = 0; Handle self = GetWindowLongPtr( win, GWLP_USERDATA); PWidget v = ( PWidget) self; UINT orgMsg = msg; Event ev; Bool hiStage = false; int i, orgCmd; Bool message_result = true; if ( !self || appDead) return DefWindowProcW( win, msg, mp1, mp2); memset( &ev, 0, sizeof (ev)); ev. gen. source = self; switch ( msg) { case WM_NCACTIVATE: // if activation or deactivation is concerned with declipped window ( e.g.self), // notify its top level frame so that it will have the chance to redraw itself correspondingly if ( is_declipped_child( self) && !Widget_is_child( hwnd_to_view(( HWND) mp2), hwnd_top_level( self))) { Handle x = hwnd_top_level( self); if ( x) SendMessage( DHANDLE( x), WM_NCACTIVATE, mp1, mp2); } break; case WM_MOUSEACTIVATE: // if pointing to non-active frame, but its declipped child is active at the moment, // cancel activation - it could produce unwilling focus changes if ( sys className == WC_FRAME) { Handle x = hwnd_to_view( GetActiveWindow()); if ( is_declipped_child(x) && Widget_is_child( x, self)) return MA_NOACTIVATE; } break; case WM_CLOSE: if ( sys className != WC_FRAME) return 0; break; case WM_COMMAND: if (( HIWORD( mp1) == 0 /* menu source */) && ( mp2 == 0)) { if ( LOWORD( mp1) <= MENU_ID_AUTOSTART) { HWND active = GetFocus(); if ( active != nil) SendMessage( active, LOWORD( mp1), 0, 0); } else if ( sys lastMenu) { PAbstractMenu a = ( PAbstractMenu) sys lastMenu; if ( a-> stage <= csNormal) a-> self-> sub_call_id(( Handle) a, LOWORD( mp1) - MENU_ID_AUTOSTART); } } break; case WM_CONTEXTMENU: { POINT a; a. x = ( short)LOWORD( mp2); a. y = ( short)HIWORD( mp2); ev. cmd = cmPopup; // mouse event ev. gen. B = ( GetKeyState( VK_LBUTTON) < 0) | ( GetKeyState( VK_RBUTTON) < 0); if ( !ev. gen. B && GetSystemMetrics( SM_MOUSEPRESENT)) GetCursorPos(( POINT*) &a); MapWindowPoints( NULL, win, &a, 1); ev. gen. P. x = a. x; ev. gen. P. y = sys lastSize. y - a. y - 1; } break; case WM_ENABLE: ev. cmd = mp1 ? cmEnable : cmDisable; hiStage = true; break; case WM_ERASEBKGND: return 1; case WM_FORCEFOCUS: if ( mp2) ((( PWidget) mp2)-> self)-> set_selected(( Handle) mp2, 1); return 0; case WM_HASMATE: *(( Handle*) mp2) = self; return HASMATE_MAGIC; case WM_IME_CHAR: if ( apc_widget_is_responsive( self)) { ev. cmd = cmKeyDown; ev. key. mod = kmUnicode; ev. key. key = kbNoKey; ev. key. code = mp1; } break; case WM_SYSKEYDOWN: case WM_SYSKEYUP: if ( mp2 & ( 1 << 29)) ev. key. mod = kmAlt; case WM_KEYDOWN: case WM_KEYUP: if ( apc_widget_is_responsive( self)) { BYTE * keyState; Bool up = ( msg == WM_KEYUP) || ( msg == WM_SYSKEYUP); Bool extended = mp2 & ( 1 << 24); UINT scan = ( HIWORD( mp2) & 0xFF) | ( up ? 0x80000000 : 0); int deadPollCount = 0; HKL kl = GetKeyboardLayout(0); // basic assignments ev. cmd = up ? cmKeyUp : cmKeyDown; ev. key. key = ctx_remap_def( mp1, ctx_kb2VK, false, kbNoKey); ev. key. code = mp1; ev. key. repeat = mp2 & 0x000000FF; // VK validations if ( extended) { int ks = ev. key. key; ev. key. key = ctx_remap_def( ks, ctx_kb2VK3, true, ks); if ( ev. key. key != ks) extended = false; // avoid (Ctrl|Alt)R+KeyPad combinations } else if ( mp1 >= VK_NUMPAD0 && mp1 <= VK_DIVIDE) extended = true; // include numpads ev. key. mod = 0 | ( extended ? kmKeyPad : 0) | (( GetKeyState( VK_SHIFT) < 0) ? kmShift : 0) | (( GetKeyState( VK_CONTROL) < 0) ? kmCtrl : 0) | (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0); keyState = guts. keyState; AGAIN: if ( PApplication(application)-> wantUnicodeInput) { WCHAR keys[ 2]; // unicode mapping switch ( ToUnicodeEx( mp1, scan, keyState, keys, 2, 0, kl)) { case 1: // char if ( lastDeadKey ) { WCHAR wcBuffer[3]; WCHAR out[3]; wcBuffer[0] = keys[0]; wcBuffer[1] = lastDeadKey; wcBuffer[2] = '\0'; if ( FoldStringW(MAP_PRECOMPOSED, (LPWSTR) wcBuffer, 3, (LPWSTR) out, 3) ) keys[0] = out[0]; } if ( !deadPollCount && ( GetKeyState( VK_MENU) < 0) && ( GetKeyState( VK_SHIFT) >= 0)) { WCHAR keys2[2]; if (( ToUnicodeEx( mp1, scan, guts. emptyKeyState, keys2, 2, 0, kl) == 1) && ( keys2[0] != keys[0])) { /* example - (AltGr+2) == '@' on danish keyboard. this hack is to tell whether the key without mods will give same character code ... */ ev. key. mod &= ~(kmAlt|kmCtrl|kmShift); } } if (!up) lastDeadKey = 0; break; case 2: { // dead key lastDeadKey = ctx_remap_def( keys[0], ctx_deadkeys, true, keys[0]); keys[ 0] = 0; ev. key. mod |= kmDeadKey; } break; case 0: // virtual key if ( deadPollCount == 0) { /* can't have character code - maybe fish out without mods? */ keyState = guts. emptyKeyState; deadPollCount = 1; goto AGAIN; } else { /* same meaning without mods, no code anyway */ keys[ 0] = 0; } if (!up) lastDeadKey = 0; break; default: ev. key. mod |= kmDeadKey; if (!up) lastDeadKey = 0; } ev. key. code = keys[ 0]; ev. key. mod |= kmUnicode; } else { BYTE keys[ 4]; switch ( ToAsciiEx( mp1, scan, keyState, (LPWORD) keys, 0, kl)) { case 1: // char if ( lastDeadKey ) { BYTE cBuffer[3]; BYTE out[3]; cBuffer[0] = keys[0]; cBuffer[1] = lastDeadKey; cBuffer[2] = '\0'; if ( FoldStringA(MAP_PRECOMPOSED, (LPSTR) cBuffer, 3, (LPSTR) out, 3) ) keys[0] = out[0]; } if ( !deadPollCount && ( GetKeyState( VK_MENU) < 0) && ( GetKeyState( VK_SHIFT) >= 0)) { BYTE keys2[4]; if (( ToAsciiEx( mp1, scan, guts. emptyKeyState, (LPWORD) keys2, 0, kl) == 1) && ( keys2[0] != keys[0])) { /* example - (AltGr+2) == '@' on danish keyboard. this hack is to tell whether the key without mods will give same character code ... */ ev. key. mod &= ~(kmAlt|kmCtrl|kmShift); } } break; case 2: { // dead key lastDeadKey = keys[0]; keys[ 0] = 0; ev. key. mod |= kmDeadKey; } break; case 0: // virtual key if ( deadPollCount == 0) { /* can't have character code - maybe fish out without mods? */ keyState = guts. emptyKeyState; deadPollCount = 1; goto AGAIN; } else { /* same meaning without mods, no code anyway */ keys[ 0] = 0; } if (!up) lastDeadKey = 0; break; default: ev. key. mod |= kmDeadKey; if (!up) lastDeadKey = 0; } ev. key. code = keys[ 0]; } // simulated key codes if ( ev. key. key == kbTab && ( ev. key. mod & kmShift)) ev. key. key = kbBackTab; if ( ev. key. code >= 'A' && ev. key. code <= 'z' && ev. key. mod & kmCtrl) { ev. key. code = toupper(ev. key. code & 0xFF) - '@'; if (!( ev. key. mod & kmShift)) ev. key. code = tolower( ev. key. code); } } break; case WM_INITMENUPOPUP: if ( HIWORD( mp2)) break; // do not use system popup case WM_INITMENU: { PMenuWndData mwd = ( PMenuWndData) hash_fetch( menuMan, &mp1, sizeof( void*)); PMenuItemReg m = nil; sys lastMenu = mwd ? mwd-> menu : nilHandle; if ( mwd && mwd-> menu && ( PAbstractMenu(mwd-> menu)->stage <= csNormal)) { m = ( PMenuItemReg) AbstractMenu_first_that( mwd-> menu, find_oid, INT2PTR(void*,mwd->id), true); hiStage = true; ev. cmd = cmMenu; ev. gen. H = mwd-> menu; ev. gen. i = m ? m-> id : 0; } if (( msg == WM_INITMENUPOPUP) && ( m == nil)) ev. cmd = 0; } break; case WM_KILLFOCUS: if (( HWND) mp1 != win) { ev. cmd = cmReleaseFocus; hiStage = true; apt_assign( aptFocused, 0); DestroyCaret(); } break; case WM_LBUTTONDOWN: ev. pos. button = mbLeft; goto MB_DOWN; case WM_RBUTTONDOWN: ev. pos. button = mbRight; goto MB_DOWN; case WM_MBUTTONDOWN: ev. pos. button = mbMiddle; goto MB_DOWN; case WM_LBUTTONUP: ev. pos. button = mbLeft; goto MB_UP; case WM_RBUTTONUP: ev. pos. button = mbRight; goto MB_UP; case WM_MBUTTONUP: ev. pos. button = mbMiddle; goto MB_UP; case WM_LBUTTONDBLCLK: ev. pos. button = mbLeft; goto MB_DBLCLK; case WM_RBUTTONDBLCLK: ev. pos. button = mbRight; goto MB_DBLCLK; case WM_MBUTTONDBLCLK: ev. pos. button = mbMiddle; goto MB_DBLCLK; case WM_LMOUSECLICK: ev. pos. button = mbLeft; goto MB_CLICK; case WM_RMOUSECLICK: ev. pos. button = mbRight; goto MB_CLICK; case WM_MMOUSECLICK: ev. pos. button = mbMiddle; goto MB_CLICK; case WM_MOUSEWHEEL: { POINT p; p. x = (short)LOWORD( mp2); p. y = (short)HIWORD( mp2); ev. cmd = cmMouseWheel; ev. pos. button = ( short) HIWORD( mp1); MapWindowPoints( nil, win, &p, 1); ev. pos. where. x = p. x; ev. pos. where. y = sys lastSize. y - p. y - 1; } goto MB_MAIN_NOPOS; case WM_MOUSEMOVE: ev. cmd = cmMouseMove; if ( self != lastMouseOver) { Handle old = lastMouseOver; lastMouseOver = self; if ( old && ( PWidget( old)-> stage == csNormal)) SendMessage(( HWND)(( PWidget) old)-> handle, WM_MOUSEEXIT, mp1, mp2); SendMessage( win, WM_MOUSEENTER, mp1, mp2); if ( !guts. mouseTimer) { guts. mouseTimer = 1; if ( !SetTimer( dsys(application)handle, TID_USERMAX, 100, nil)) apiErr; } } goto MB_MAIN; case WM_MOUSEENTER: ev. cmd = cmMouseEnter; goto MB_MAIN; case WM_MOUSEEXIT: ev. cmd = cmMouseLeave; goto MB_MAIN; MB_DOWN: ev. cmd = cmMouseDown; goto MB_MAINACT; MB_UP: ev. cmd = cmMouseUp; goto MB_MAINACT; MB_DBLCLK: ev. pos. dblclk = 1; MB_CLICK: ev. cmd = cmMouseClick; goto MB_MAINACT; MB_MAINACT: if ( !is_apt( aptEnabled) || !apc_widget_is_responsive( self)) { if ( ev. cmd == cmMouseDown || (ev. cmd == cmMouseClick && ev. pos. dblclk)) MessageBeep( MB_OK); return 0; } goto MB_MAIN; MB_MAIN: if ( ev. cmd == cmMouseDown && !is_apt( aptFirstClick)) { Handle x = self; while ( dsys(x) className != WC_FRAME && ( x != application)) x = (( PWidget) x)-> owner; if ( x != application && !local_wnd( GetActiveWindow(), DHANDLE( x))) { ev. cmd = 0; // yes, we abandon mousedown but we should force selection: if ((( PApplication) application)-> hintUnder == self) v-> self-> set_hintVisible( self, 0); if (( v-> options. optSelectable) && ( v-> selectingButtons & ev. pos. button)) apc_widget_set_focused( self); } } ev. pos. where. x = (short)LOWORD( mp2); ev. pos. where. y = sys lastSize. y - (short)HIWORD( mp2) - 1; MB_MAIN_NOPOS: ev. pos. mod = 0 | (( mp1 & MK_CONTROL ) ? kmCtrl : 0) | (( mp1 & MK_SHIFT ) ? kmShift : 0) | (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0) | apc_pointer_get_state(self) ; break; case WM_MENUCHAR: { int key; ev. key. key = ctx_remap_def( mp1, ctx_kb2VK2, false, kbNoKey); ev. key. code = mp1; ev. key. mod |= (( GetKeyState( VK_SHIFT) < 0) ? kmShift : 0) | (( GetKeyState( VK_CONTROL) < 0) ? kmCtrl : 0) | (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0); if (( ev. key. mod & kmCtrl) && ( ev. key. code <= 'z')) ev. key. code += 'A' - 1; key = CAbstractMenu-> translate_key( nilHandle, ev. key. code, ev. key. key, ev. key. mod); if ( v-> self-> process_accel( self, key)) return MAKELONG( 0, MNC_CLOSE); } break; case WM_SYNCMOVE: { Handle parent = v-> self-> get_parent(( Handle) v); if ( parent) { Point pos = var self-> get_origin( self); ev. cmd = cmMove; ev. gen. P = pos; if ( pos. x == var pos. x && pos. y == var pos. y) ev. cmd = 0; } } break; case WM_MOVE: { Handle parent = v-> self-> get_parent(( Handle) v); if ( parent) { Point sz = CWidget(parent)-> get_size( parent); ev. cmd = cmMove; ev. gen . P. x = ( short) LOWORD( mp2); ev. gen . P. y = sz. y - ( short) HIWORD( mp2) - sys yOverride; if ( is_apt( aptTransparent)) InvalidateRect( win, nil, false); } } break; case WM_NCHITTEST: if ( guts. focSysDialog) return HTERROR; // dlg protect code - protecting from user actions if ( !guts. focSysDisabled && ( Application_map_focus( application, self) != self)) return HTERROR; break; case WM_PAINT: ev. cmd = cmPaint; if ( ( sys className == WC_CUSTOM) && ( var stage == csNormal) && ( list_index_of( &guts. transp, self) >= 0) ) return 0; break; case WM_QUERYNEWPALETTE: return palette_change( self); case WM_PALETTECHANGED: if (( HWND) mp1 != win) { Handle mp = hwnd_to_view(( HWND) mp1); if ( mp && ( hwnd_top_level( mp) == hwnd_top_level( self))) return 0; palette_change( self); } break; case WM_POSTAL: ev. cmd = cmPost; ev. gen. H = ( Handle) mp1; ev. gen. p = ( void *) mp2; break; case WM_PRIMA_CREATE: ev. cmd = cmSetup; break; case WM_SETFOCUS: if ( guts. focSysDialog) return 1; // dlg protect code - general case if ( !guts. focSysDisabled && !guts. focSysGranted) { Handle hf = Application_map_focus( application, self); if ( hf != self) { PostMessage( win, WM_FORCEFOCUS, 0, ( LPARAM) hf); return 1; } } if (( HWND) mp1 != win) { ev. cmd = cmReceiveFocus; hiStage = true; apt_assign( aptFocused, 1); cursor_update( self); } break; case WM_SETVISIBLE: if ( list_index_of( &guts. transp, self) < 0) { if ( v-> stage <= csNormal) ev. cmd = mp1 ? cmShow : cmHide; hiStage = true; apt_assign( aptVisible, mp1); } break; case WM_SIZE: ev. cmd = cmSize; ev. gen. R. left = sys lastSize. x; ev. gen. R. bottom = sys lastSize. y; sys lastSize. x = ev. gen. R. right = ev. gen . P. x = ( short) LOWORD( mp2); sys lastSize. y = ev. gen. R. top = ev. gen . P. y = ( short) HIWORD( mp2); if ( ev. gen. R. top != ev. gen. R. bottom) { int delta = ev. gen. R. top - ev. gen. R. bottom; Widget_first_that( self, move_back, &delta); if ( is_apt( aptFocused)) cursor_update(( Handle) self); } if ( sys sizeLockLevel == 0 && var stage <= csNormal) var virtualSize = sys lastSize; break; case WM_TIMER: { int id = mp1 - 1; if ( id >= 0 && id < sys timeDefsCount) ev. gen. H = ( Handle) sys timeDefs[ id]. item; if ( ev. gen. H) { v = ( PWidget)( self = ev. gen. H); ev. cmd = cmTimer; } } break; case WM_WINDOWPOSCHANGING: { LPWINDOWPOS l = ( LPWINDOWPOS) mp2; if ( sys className == WC_CUSTOM) { if (( l-> flags & SWP_NOSIZE) == 0) { ev. cmd = cmCalcBounds; ev. gen. R. right = l-> cx; ev. gen. R. top = l-> cy; } } if (( l-> flags & SWP_NOZORDER) == 0) zorder_sync( self, win, l); } break; case WM_WINDOWPOSCHANGED: { LPWINDOWPOS l = ( LPWINDOWPOS) mp2; if (( l-> flags & SWP_NOZORDER) == 0) PostMessage( win, WM_ZORDERSYNC, 0, 0); if (( l-> flags & SWP_NOSIZE) == 0) { sys yOverride = l-> cy; SendMessage( win, WM_SYNCMOVE, 0, 0); } if ( l-> flags & SWP_HIDEWINDOW) SendMessage( win, WM_SETVISIBLE, 0, 0); if ( l-> flags & SWP_SHOWWINDOW) SendMessage( win, WM_SETVISIBLE, 1, 0); } break; case WM_ZORDERSYNC: ev. cmd = cmZOrderChanged; break; }