Toon posts:

[Win32/C] SetForegroundWindow werkt niet met WinXP

Pagina: 1
Acties:

Verwijderd

Topicstarter
Bij het starten van mijn C-programma gebeuren twee dingen:
1. Aanroep Visual Basic programma ivm logonfunctie
2. SetForeGroundWindow vanuit het C-programma om na het beëindigen van het VB-programma weer op de voorgrond te komen.

Met Windows98 werkte dit goed, maar onder XP werkt dit niet. De taakbalkknop knippert en het venster is wel zichtbaar, maar staat niet op de voorgrond. Ik ben erachter gekomen dat XP zodanig veranderd is, dat programma's dit niet meer mogen doen. In mijn geval zijn de twee programma's (C en VB) voor de gebruiker een logisch geheel en is het onhandig als de gebruiker na het inlogvenster ineens de focus kwijt is.

Wie heeft een oplossing?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Focus stealing is al heel lang een setting die je oa. met de TweakUI PowerToy van MS zelf aan en uit kunt zetten.

Ik snap echter je volgorde niet helemaal: je zegt dat je vanuit C-progsel A het VB-progsel B opstart, en wil nadat B klaar is automatisch A op de voorgrond hebben..... wie heeft A dan gehide? :?

Professionele website nodig?


Verwijderd

Topicstarter
Focus stealing is al heel lang een setting die je oa. met de TweakUI PowerToy van MS zelf aan en uit kunt zetten.
Klopt. Het programma draait echter op meerdere pc's en ik heb niet in de hand of mensen deze tweak gebruiken.
Ik snap echter je volgorde niet helemaal: je zegt dat je vanuit C-progsel A het VB-progsel B opstart, en wil nadat B klaar is automatisch A op de voorgrond hebben..... wie heeft A dan gehide? :?
Het VB-programma wordt na het inloggen beëindigd. De besturing keert dan weer terug in het C-programma.

  • Guillome
  • Registratie: Januari 2001
  • Niet online

Guillome

test

Ik weet niet of je er wat aan hebt, maar het ligt niet aan XP.
Ik kan het in Delphi namelijk gewoon gebruiken.
In deze code werkt het op 2k en XP:
code:
1
2
3
4
5
6
7
8
9
function TForm2.ShowInstance(hWnd : Integer) : Boolean;
Var Style: Integer;
begin
  Style := GetWindowLong(hWnd, GWL_STYLE);
  If (Style = 114229248) or (Style = 919535616) or (Style = 651100160) Then
    ShowWindow(hWnd, SW_SHOWNORMAL or SW_RESTORE);
  SetForegroundWindow(hWnd);
  Result := True;
End;


Misschien heb je er wat aan?

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Verwijderd schreef op 12 februari 2004 @ 13:21:
[...]
Het VB-programma wordt na het inloggen beëindigd. De besturing keert dan weer terug in het C-programma.
Dat bedoel ik dus: dit gaat toch automatisch goed? :?

App A heeft focus, lanceert app B die focus krijgt. Zodra app B dan gesloten wordt zal Windows de focus teruggeven aan de vorig actieve app, zijnde A. Omdat de windows van B weer weg zijn ligt A dus automatisch op de voorgrond. Ik snap je probleem dus niet echt...

Wat hierbij fout kan gaan is dat de user tijdens het gebruik van B een applicatie C heeft geopend. Op dat moment zal na het sluiten van B de focus teruggaan naar C ipv A, maar dat is juist het hele idee van die focus-steal setting: dat hoort zo omdat de gebruiker dat verwacht. Dus alles werkt 'exactly as advertised' :Y)

Professionele website nodig?


Verwijderd

Topicstarter
App A heeft focus, lanceert app B die focus krijgt. Zodra app B dan gesloten wordt zal Windows de focus teruggeven aan de vorig actieve app, zijnde A. Omdat de windows van B weer weg zijn ligt A dus automatisch op de voorgrond.
Als ik het programma draai (zonder tussentijds andere programma's te starten) krijg ik toch echt een window zonder focus te zien. Op het moment dat A app B start is er van A nog geen venster in beeld. Dat kan de reden zijn dan B geen focus aan A kan teruggeven. Op het moment dat A, na afsluiten B, een venster toont, krijgt dit dus geen focus.

Overigens levert de delphi-code (omgezet naar C) niets op.

[ Voor 7% gewijzigd door Verwijderd op 12-02-2004 13:57 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Ben je niet stiekem SetFocus en SetForegroundWindow door de war aan het halen? Wat jij wilt is namelijk SetFocus, absoluut geen SetForegroundWindow.

Professionele website nodig?


Verwijderd

Topicstarter
Setfocus geprobeerd maar dit maakt geen verschil.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

[q]Windows 98/Me: The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:
  • The process is the foreground process.
  • The process was started by the foreground process.
  • The process received the last input event.
  • There is no foreground process.
  • The foreground process is being debugged.
  • The foreground is not locked (see LockSetForegroundWindow).
  • The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
  • Windows 2000/XP: No menus are active.
  • With this change, an application cannot force a window to the foreground while the user is working with another window. Instead, Foreground and Background Windows will activate the window (see SetActiveWindow) and call the function to notify the user. However, on Microsoft® Windows® 98 and Windows Millennium Edition (Windows Me), if a nonforeground thread calls SetForegroundWindow and passes the handle of a window that was not created by the calling thread, the window is not flashed on the taskbar. To have SetForegroundWindow behave the same as it did on Windows 95 and Microsoft Windows NT® 4.0, change the foreground lock timeout value when the application is installed. This can be done from the setup or installation application with the following function call: SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
Wat jij wilt hebben is waarschijnlijk gewoon SetWindowPos (hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)

[ Voor 4% gewijzigd door .oisyn op 12-02-2004 14:55 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Verwijderd schreef op 12 februari 2004 @ 13:00:
...
2. SetForeGroundWindow vanuit het C-programma om na het beëindigen van het VB-programma weer op de voorgrond te komen.
Zoals eerder gemeld is "Foreground stealing" geprobeerd om tot een minimum te beperken.

Hierzo heb je een Delphi oplossing. Dit kan recht-toe-rechtaan vertaald worden naar C.
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function ForceForegroundWindow(hWnd: HWND): Boolean;
const
  SPI_GETFOREGROUNDLOCKTIMEOUT = $2000;
  SPI_SETFOREGROUNDLOCKTIMEOUT = $2001;
 
var
  thrForeground: DWORD;
  thrThis      : DWORD;
  dTimeout     : DWORD;
 
begin
  if IsIconic(hWnd) then ShowWindow(hWnd, SW_RESTORE);
  if GetForegroundWindow() = hWnd then
    Result := True
  else begin
    if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or
       ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and ((Win32MajorVersion > 4) or
       ((Win32MajorVersion = 4) and (Win32MinorVersion > 0)))) then begin

      Result := False;
      thrForeground := GetWindowThreadProcessID(GetForegroundWindow(), nil);
      thrThis       := GetWindowThreadProcessID(hWnd, nil);

      if AttachThreadInput(thrThis, thrForeground, True) then begin
        BringWindowToTop(hWnd);
        SetForegroundWindow(hWnd);
        AttachThreadInput(thrThis, thrForeground, False);
        Result := (GetForegroundWindow() = hWnd);
      end;

      if not Result then begin
        SystemParametersInfo( SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @dTimeout, 0);
        SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0),
                             SPIF_SENDCHANGE);
        BringWindowToTop(hWnd);
        SetForegroundWindow(hWnd);
        SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(dTimeout),
                             SPIF_SENDCHANGE);
      end;
    end else begin
      BringWindowToTop(hWnd);
      SetForegroundWindow(hWnd);
    end;

    Result := (GetForegroundWindow() = hWnd);
  end;
end;

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Oh excuus, het moet mij compleet ontgaan zijn dat we voortaan altijd kant-en-klare oplossingen geven :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
SetWindowPos lijkt ook niet te werken.

De Delphi-oplossing heb ik geprobeerd. Het deel met AttachThreadInput geeft in ieder geval enig resultaat. De ene keer werkt het wel, de andere keer niet.

Op deze pagina staat onder 'methode 2' een dergelijke oplossing waarbij je eerst een attach van het foreground thread doet en daarna SetWindowForeGround.

Dit werkt dus meestal wel, maar niet altijd. Tips voor betere oplossingen zijn welkom.

Verwijderd

Volgens mij zou je ook nog (als extra) het volgende kunnen implementeren.

De applicatie 'always on top' maken. En dit dan weer herstellen. Eventueel natuurlijk ook nog de Z-Order aanpassen.
Mogelijkheid dat er nog geen focus is, maar de applicatie is dan in ieder geval wel zichtbaar.

Verwijderd

Topicstarter
De zichtbaarheid van de applicatie is niet het probleem. Het gaat om de inputfocus. Kennelijk is hier in XP geen 100% afdoende oplossing voor.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Verwijderd schreef op 12 februari 2004 @ 18:09:
De zichtbaarheid van de applicatie is niet het probleem. Het gaat om de inputfocus. Kennelijk is hier in XP geen 100% afdoende oplossing voor.
Jawel maar die is met policies dichtgetimmert :z

Professionele website nodig?


  • Guillome
  • Registratie: Januari 2001
  • Niet online

Guillome

test

Waarom werkt mijn manier perfect bij mij?
En bij anderen?
Deze zet IE vensters naar de voorgrond.

If then else matters! - I5 12600KF, Asus Tuf GT501, Gigabyte Gaming OC 16G 5080 RTX, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

XLerator schreef op 13 februari 2004 @ 00:21:
Waarom werkt mijn manier perfect bij mij?
En bij anderen?
Deze zet IE vensters naar de voorgrond.
Omdat die policies default open staan.

Professionele website nodig?

Pagina: 1