Exemplo n.º 1
0
Handle
Widget_popup( Handle self, Bool set, Handle popup)
{
    enter_method;
    if ( var-> stage > csFrozen) return nilHandle;
    if ( !set)
        return var-> popupMenu;

    if ( popup && !kind_of( popup, CPopup)) return nilHandle;
    if ( popup && PAbstractMenu( popup)-> owner != self)
        my-> set_popupItems( self, CAbstractMenu( popup)-> get_items( popup, ""));
    else
        var-> popupMenu = popup;
    return nilHandle;
}
Exemplo n.º 2
0
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;
   }