Warum kennt der Sack LockSetForegroundWindow nicht?!



  • Moin!

    Beim Versuch, LockSetForegroundWindow zu verwenden, bekomme ich folgende Linker-Meldung:

    .\PrintWindowEx.cpp(84) : error C2065: 'LSFW_LOCK': nichtdeklarierter Bezeichner
    .\PrintWindowEx.cpp(84) : error C3861: "LockSetForegroundWindow": Bezeichner wurde nicht gefunden.
    .\PrintWindowEx.cpp(103) : error C2065: 'LSFW_UNLOCK': nichtdeklarierter Bezeichner
    .\PrintWindowEx.cpp(103) : error C3861: "LockSetForegroundWindow": Bezeichner wurde nicht gefunden.
    

    Der Aufruf ist korrekt:

    LockSetForegroundWindow(LSFW_LOCK);
    

    Ich arbeite mit dem VS2005 unter WinXP x64. Die windows.h habe ich inkludiert. In den Optionen (Linker->Eingabe->Zusätzliche Abhängigkeiten) ist nichts eingetragen, was bedeutet, dass die Standard-Libs gelinkt werden. Dabei ist auch die user32.lib, die für die Funktion benötigt wird.

    Also warum kennt der Sack die Funktion nicht? Habe ich mich nicht alle Voraussetzungen erfüllt?

    Für eine schnelle Antwort wäre ich sehr dankbar, da ich das heute auf der Arbeit brauche.

    Gruß Matze



  • _matze schrieb:

    Beim Versuch, LockSetForegroundWindow zu verwenden, bekomme ich folgende Linker-Meldung:

    Die Meldungen kommen vom Compiler, nicht vom Linker.

    _matze schrieb:

    Also warum kennt der Sack die Funktion nicht? Habe ich mich nicht alle Voraussetzungen erfüllt?

    MSDN Library schrieb:

    Minimum operating systems Windows Me, Windows 2000

    Hast du die entsprechenden Defines gesetzt?



  • Erstens beschwert sich da nicht der Linker, sondern der Compiler (Linker-Meldungen beginnen mit LNK...).

    Zweitens: Schau mal in der MSDN nach, welcher Header für diese Funktion tatsächlich benötigt wird (und welche Version du hast bzw. brauchst)

    Drittens: Wenn du dein System als "Sack" bezeichnest, nimmt es dir das irgendwann übel 😃



  • Na keine Ahnung, bei mir ists gar nicht im Header drin, aber ich benutze auch eine uralte Platform SDK immoment. Vielleicht musst du eine neuere installieren, schau mal ob es im Winuser.h bei dir deklariert ist. Musst du vielleicht WINVER oder so setzen? Oder sonst einfach das Handle zu user32.dll mit LoadLibrary() holen und die Funktion mit GetProcAddress holen und aufrufen, so funzts bei mir 🤡



  • Erstmal danke für die flotten Antworten!

    Ja, ihr habt ja Recht, ein Compiler-Fehler isses, hab mich vertan.

    Die defines hab ich drinnen, daran sollte es eigentlich nicht liegen.

    #define _WIN32_WINNT 0x0501
    #define _WIN32_WINDOWS 0x0401
    

    Tut es aber scheinbar doch! Ein kleiner Auszug aus der winuser.h:

    WINUSERAPI
    BOOL
    WINAPI
    SetForegroundWindow(
        __in HWND hWnd);
    
    #if(_WIN32_WINNT >= 0x0500)
    WINUSERAPI
    BOOL
    WINAPI
    AllowSetForegroundWindow(
        __in DWORD dwProcessId);
    
    #define ASFW_ANY    ((DWORD)-1)
    
    WINUSERAPI
    BOOL
    WINAPI
    LockSetForegroundWindow(
        __in UINT uLockCode);
    
    #define LSFW_LOCK       1
    #define LSFW_UNLOCK     2
    
    #endif /* _WIN32_WINNT >= 0x0500 */
    

    Weder LockSetForegroundWindow noch AllowSetForegroundWindow kann ich benutzen. Die SetForegroundWindow funktioniert natürlich.
    Da diese Funktionen ansonsten identisch deklariert werden, muss es ja an der Bedingung, also an _WIN32_WINNT liegen. Dieses habe ich doch aber auf 0x501 gestellt. Die defines kommen auch vor dem "#include <winuser.h>".

    Ich habe mir nie vorstellen können, Amok zu laufen. Bis heute...



  • Ich möchte euch auch mal mein Hauptproblem erklären. Vielleicht kann ich ja auch LockSetForegroundWindow verzichten.

    Ich habe eine Funktion geschrieben, die ein Fenster-Handle übergeben bekommt und dieses Fenster dann gestreckt und zentriert auf dem Drucker ausgibt (mit PrintDialog).
    Dazu mache ich einen Screenshot vom Desktop mit den entsprechenden Koordinaten.

    Mein Problem ist, dass manchmal der PrintDialog noch (oder wieder?) über dem Fenster liegt, obwohl ich dachte, ich hätte mit SetForegroundWindow (und folgendem Sleep(50)) dafür gesorgt, dass das Zielfenster auf jeden Fall vorne liegt. Übrigens hat das bei mir IMMER und bei JEDEM Test geklappt. Erst bei dem Kollegen, der die DLL nutzen soll, ist das Phänomen aufgetreten.

    Der verdammte Standard-Dialog will sich also scheinbar nicht so recht vom Bildschirm verdrängen lassen. Auch kann ich ja nicht feststellen, ob er bereits geschlossen wurde oder nicht. Das Delay auf 250ms heraufzusetzen, hat auch nicht viel gebracht. Außerdem wäre das eine unschöne Lösung.

    Also habe ich gedacht, LockSetForegroundWindow ist vielleicht die Funktion, die ich brauche, um das Fenster meiner Begierde unmissverständlich in den Vordergrund zu stellen. Und da haben die bekannten Probleme angefangen...

    Wenn also jemand dieses Phänomen kennt und einen besseren Lösungsansatz weiß, bitte her damit!

    Gruß Matze



  • Erstens: Stehen die #define's denn vor deinem Include (im Zweifelsfall kannst du sie auch gleich in die Compiler-Optionen aufnehmen, da bist du auf der sicheren Seite).

    Zweitens: Es ist (vermutlich) der falsche Ansatz, den Desktop zu fotografieren. Lass dir lieber vom Zielfenster einen Device Context (HDC) geben und hol den Inhalt des Fensters von dort, da hast du afaik keine Probleme mit überlappenden Fremdfenstern.



  • _matze schrieb:

    Die defines kommen auch vor dem "#include <winuser.h>".

    Den Ansatz, nur vom Fenster selbst (und über diesen Kontext) zu capturen, habe ich anfangs verfolgt, da war aber irgendetwas, das mich dazu bewogen hat, über den Desktop und die Abmessungen des Fensters zu gehen. Ich weiß nicht mehr genau, was da nicht funktioniert hat (der betreffende Code stammt noch aus einem anderen, älteren Programm von mir).
    Ich würde auch ungern alles wieder umkrempeln. Aber wenn's so nicht klappt, werde ich dass wohl müssen...

    Unabhängig vom Hauptproblem interessiert mich die Lock..Window Geschichte aber doch brennend. Ich komme einfach nicht dahinter, wo der Fehler liegt.

    EDIT P.S.: Gerade kam die Erinnerung zurück! Ich habe damals Probleme gehabt, ein Fenster komplett mit Parent-Bereich zu capturen. Die Lösung mit dem Desktop hat dann viel besser funktioniert. Erst danach habe ich gelesen, dass es so tolle Funktionen wie OffsetRect (oder so ähnlich) gibt, mit deren Hilfe man dann doch das komplette Fenster erfassen kann.
    So betrachtet ist es natürlich kein Problem, alles wieder umzustricken (wenn auch ärgerlich).

    Die Sache mit Lockschlagmichtot läuft weiterhin. Wer mir die Lösung präsentiert, bekommt den Titel "Programmierer des Tages"!

    Gruß Matze


  • Mod

    1. winuser.h nie selbst includen. einfach nur die windows.h!
    2. Vor dem ersten Verwenden der windows.h muss der entsprechende define WINVER gesetzt werden! D.h. meistens in der stdafx.h. Späteres setzen wird durch die Compile Gards letzten Endes wirkungslos.



  • Ich habe windows.h inkludiert. winuser.h habe ich auch mal kurz ausprobiert, aber natürlich ohne Erfolg.

    Die defines werden ganz am Anfang gesetzt. Im Moment sieht es so aus:

    #define _WIN32_WINNT 0x0500
    //#define _WIN32_WINDOWS 0x0401
    #define WINVER 0x0500
    
    #include "stdafx.h"
    #include <windows.h>
    #include <commdlg.h>
    #include <math.h>
    #include "PrintWindowEx.h"
    

    Ich habe auch probiert, die stdafx.h nach ganz oben zu setzen, ohne Unterschied.

    Ich habe langsam die Vermutung, dass es da noch irgendeine Einstellung im VS gibt, die mir die defines überschreibt. Ich habe jedoch nichts Entsprechendes finden können.

    EDIT: Ich habe auch mal probiert, den Prototypen und die defines aus der winuser.h direkt in meinen Code zu kopieren. Aber natürlich hat es nicht geklappt, so wie alles heute...



  • Mach es so, wie CStoll schon geschrieben hat. Das ist viel besser und damit hast du dieses Fenster Problem dann nicht mehr.



  • Erstmal danke für die reichlichen und schnellen Antworten!

    Ich habe die Funktion so umgebaut, dass aus dem DC des Zielfensters geblittet wird. Dank OffsetRect ist das ja kein Problem. Um so ärgerlicher war die Erkenntnis, dass das Problem weiterhin bestand! Aber ich denke, ich habe es soeben gelöst.

    Ich traue mich kaum, das hier zu sagen. Zum Glück bin ich noch C++-Anfänger, da ist's nicht ganz so peinlich.

    Ich bin stutzig geworden, als ich den Sleep-Befehl testweise von 50ms auf 1000ms 'raufgesetzt habe. Da war zwar nicht mehr der PrintDialog zu sehen, aber der darunter liegende Bereich war noch nicht neu gezeichnet worden => UpdateWindow war natürlich die Lösung. Und der Sleep hat wohl dafür gesorgt, dass der PrintDialog Zeit zum Verschwinden hat, jedoch hat er gleichzeitig verhindert, dass das Fenster neu gezeichnet wird (das war mir nicht bewusst).

    Jedenfalls werde ich das Ganze jetzt so ca. 1.000.000 testen und hoffen, das alles gut geht...

    Gruß Matze

    P.S.: Bei LockSetForegroundWindow hat immmer noch keiner eine Lösung? Würde mich wirklich interessieren, zumal ich das Problem ja irgendwann mit dieser oder anderen Funktionen wieder bekommen werde.


  • Mod

    [quote="_matze"]

    #define _WIN32_WINNT 0x0500
    //#define _WIN32_WINDOWS 0x0401
    #define WINVER 0x0500
    
    #include "stdafx.h"
    #include <windows.h>
    #include <commdlg.h>
    #include <math.h>
    #include "PrintWindowEx.h"
    

    Das kann doch nicht gehen!!!
    Der gesamte Code vor #include "stdafx.h" wird ignoriert!
    Wie sieht Deine stdafx.h aus? Dort gehört der #define WINVER ganz oben rein.



  • <----------------------------------------->
    Der Programmierer des Tages ist gefunden!
    <----------------------------------------->

    Dank an Martin Richter!

    Ich hatte "#include stdafx.h" auch mal nach ganz oben gesetzt, da ich irgendwo gelesen hatte, dass das so sein soll. Hat aber keinen Effekt gehabt (hab ich eben nochmal getestet).

    Ein "#define WINVER 0x0500" in der stdafx.h hat auch nix gebracht, sehr wohl aber "#define _WIN32_WINNT 0x0500"! So kann ich die Lock..Window Funktion nutzen (auch wenn ich sie für dieses Projekt nicht mehr brauche).

    Jetzt begreife ich auch, warum es nicht geklappt hat, dieses define direkt vor "#include windows.h" zu packen. Die wird ja schon in der stdafx.h inkludiert, und somit auch die winuser.h.

    Durch solche Geschichten wird einem der Einstieg in C++ schwer gemacht! Ich wünche mir meinen guten, alten Clipper zurück...

    Im Ernst, du kannst doch schon verstehen, dass ein Anfänger da nicht so leicht drauf kommt, oder?

    Gruß Matze


Anmelden zum Antworten