Seite 2 von 2

Re: Eigenes Programm inden Vordergrund holen

Verfasst: Mi, 24. Feb 2016 8:50
von AUGE_OHR
grummel ... nun hab ich auch das Problem :(

der Witz : ich habe es auch in der AppSys und da funktioniert es d.h. das Programm wird in den Vordergrund geholt.
so bekommt man es vom "blinken" tatsächlich in den Vordergrund ... nicht schön aber so geht es (wieder)

Code: Alles auswählen

#define SW_HIDE            0
#define SW_SHOWNORMAL      1
#define SW_NORMAL          1
#define SW_SHOWMINIMIZED   2
#define SW_SHOWMAXIMIZED   3
#define SW_MAXIMIZE        3
#define SW_SHOWNOACTIVATE  4
#define SW_SHOW            5
#define SW_MINIMIZE        6
#define SW_SHOWMINNOACTIVE 7
#define SW_SHOWNA          8
#define SW_RESTORE         9
#define SW_SHOWDEFAULT     10
#define SW_FORCEMINIMIZE   11
#define SW_MAX             11
#define SW_PARENTCLOSING   1
#define SW_OTHERZOOM       2
#define SW_PARENTOPENING   3
#define SW_OTHERUNZOOM     4

METHOD EditForm:SwitchFocus()

   IF ::lHaveFocus = .F.
      SetForegroundWindow(::nHwnd)
      BringWindowToTop(::nHwnd)
      // minimieren
      ShowWindow(::nHwnd, SW_MINIMIZE )
      // wiederherstellen
      ShowWindow(::nHwnd, SW_RESTORE )

      // Xbase++ Dialog
      SetAppWindow(::_EditForm)
      // XbPart
      SetAppFocus( ::oValues )
   ENDIF
RETURN NIL

Re: Eigenes Programm inden Vordergrund holen

Verfasst: Mi, 24. Feb 2016 9:44
von brandelh
Im beiliegenden Testprogramm habe ich die Optionen durchprobiert.

1. SetAppWindow() => :toBack(), oDlg:toFront() - in dem Falle das CMD Fenster, der Dialog bleibt wo er ist, also nicht genau

2. oDlg => :toBack(), oDlg:toFront() - in dem Falle wird das Fenster genau definiert und es funktioniert "im Prinzip" ;-)

Beide Möglichkeiten beziehen sich jedoch auf SetAppWindow() selbst, d.h. man kann nur innerhalb seiner Anwendung damit "to Front" kommen ...

Code: Alles auswählen

      oDlg:alwaysOnTop := .t.
      oDlg:configure()
holt das Fenster auf jeden Fall ganz nach vorne, egal welches normale Fenster grad aktiv ist (wenn das auch "alwaysOnTop" ist, weiß ich nicht was passiert).
aber

Code: Alles auswählen

      oDlg:alwaysOnTop := .f.
      oDlg:configure()
bringt es nicht nach hinten, dafür muss man beides kombinieren:

Code: Alles auswählen

      oDlg:alwaysOnTop := .f.
      oDlg:configure()
      oDlg:toBack()
...
      oDlg:alwaysOnTop := .t.
      oDlg:configure()
      oDlg:toFront()
Ich habe das beiliegende Programm mit 1.90.355 auf Win 7 getestet, mal sehen ob es unter Win10 auch noch geht ;-)

Re: Eigenes Programm inden Vordergrund holen

Verfasst: Mi, 24. Feb 2016 21:02
von AUGE_OHR
hi,

es gibt noch eine einfachere Möglichkeit. wie ich schon sagte funktioniert der Code in der AppSys ohne Probleme.

wenn man also das Programm nach vorne holen will startet man es einfach nochmals ;)

Code: Alles auswählen

METHOD EditForm:SwitchFocus()
   IF ::lHaveFocus = .F.
      RunShell( "","test.exe",.T.,.F.)
   ENDIF
RETURN NIL

Re: Eigenes Programm inden Vordergrund holen

Verfasst: Mi, 24. Feb 2016 23:10
von AUGE_OHR
Antwort von Pablo.
> try

Code: Alles auswählen

@ot4xb:ForceForegroundWindow( hWnd )
das ist keine "normale" API Function sondern eine ot4xb Function. deshalb nützt ein Suche bei Google nichts.
---
hier der Auszug aus dem Source WndTool.CPP

Code: Alles auswählen

DWORD OT4XB_API ot4xb_call_in_gui_thread_(ULONG np, DWORD dwfp , ... )
{
   DWORD dwResult = 0;
   if( _hWndDelegate_ )
   {
      DWORD * pStack = (DWORD*) _xgrab( (np + 2) * sizeof(DWORD) );
      ULONG n = np;
      va_list pva;
      pStack[n] = dwfp;
      va_start(pva,dwfp);
      while(n){n--;pStack[n] = va_arg(pva,DWORD);}
      dwResult = (DWORD) SendMessage(_hWndDelegate_,_nMsgCall32_,(WPARAM)np,(LPARAM)pStack);
   }
   return dwResult;
}


void OT4XB_API  ot4xb_ForceForegroundWindow(HWND hWnd)
{
   if(!IsWindow(hWnd)) return;
   DWORD nTimeOut       = 0;
   HWND  hPrevFWnd      = GetForegroundWindow();
   DWORD nNewThreadId   = GetCurrentThreadId();
   DWORD nOldThreadId   = GetWindowThreadProcessId(hPrevFWnd,0);
   if(nNewThreadId != nOldThreadId)
   {
      AttachThreadInput(nNewThreadId, nOldThreadId, TRUE);
      SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,0,&nTimeOut,0);
      SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
      if(AllowSetForegroundWindow_fp){ (*AllowSetForegroundWindow_fp)(-1);}
      SetForegroundWindow(hWnd);
      SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,(void*)nTimeOut,SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
      AttachThreadInput(nNewThreadId, nOldThreadId, FALSE);
      return;
   }
   SetForegroundWindow(hWnd);
}
//----------------------------------------------------------------------------------------------------------------------
void OT4XB_API ForceForegroundWindow(HWND hWnd)
{
   _ot4xb_gen_hwnd_delegate_(hWnd);
   ot4xb_call_in_gui_thread_(  1 , (DWORD) ot4xb_ForceForegroundWindow , hWnd );
}

Re: Eigenes Programm inden Vordergrund holen

Verfasst: Do, 25. Feb 2016 7:36
von satmax
Danke Jimmy und Pablo!

All you need is

Code: Alles auswählen

RestoreWindow(hWndToTop)
@ot4xb:ForceForegroundWindow( hWndToTop )
Damit funktionieren alle Variationen die ich getestet habe.