C/C ++ - Windows - Sådan holder du styr på HWND kontekstdata

Indlæg af Hanne Mølgaard Plasc

Problem



Antag at du har flere vinduer (HWND'er) i samme vinduesklasse åben i Windows. Hvordan holder du styr på kontekstdataene i vinduet, så vinduet 1 f.eks. Ikke bliver ændret, når brugeren forsøgte at skrive vindue 2?


CreateWindow () vender ikke tilbage, før WndProc () er blevet kaldt flere gange, så du kan ikke indstille den resulterende HWND til kontekstdataene og foretage et opslag i WndProc (), du skal indstille den i WndProc ().


WndProc () har ikke direkte kontekstoplysningerne sendt til det, undtagen i vinduet oprettelsesmeddelelser, men desværre er vinduesoprettelsesbeskeder ikke de første meddelelser, der skal sendes til WndProc (). Nej, jeg finder ting som WM\_SIZE, WM\_NCSIZE, og endda nogle andre er bestået, før jeg nogensinde ser WM\_CREATE.


Lagring af HWND i en tilknyttet liste type lagermekanisme ville være ineffektiv med store mængder af vinduer: hver kontrol i et vindue er simpelthen en anden type vindue og derfor en anden HWND, som du skal holde styr på; efter nogle få hundrede kontroller vil søgning på den tilknyttede liste for HWND være en stor flaskehals i programmet efter et par dusin beskeder sendes til programmet i løbet af kort tid!


Fra hvad jeg hører, bruger nogle mennesker SetWindowLong () - men jeg hører også, at nogle biblioteker også gerne bruger det også til at gemme deres egne kontekstoplysninger adskilt fra programmet, og at vinduesdatakollisioner undertiden kan forekomme. Hvordan kan det undgås?

Bedste reference


hvis jeg forstår dig korrekt, vil du undgå et vindue til at fange meddelelserne fra en anden. En måde at undgå dette på er at bruge løsningen foreslået i denne tråd, der holder styr på de vinduer, der er oprettet af dig og sørger for, at de korrekte vinduer får de meddelelser, der er knyttet til det, ved at lagre markøren for den, der ringer op i GWL\_USERDATA. [10]


// ...
m\_hWnd = CreateWindowEx(0,"Classname","Title",WS\_OVERLAPPEDWINDOW,
                        CW\_USEDEFAULT,CW\_USEDEFAULT,
                        320,200,NULL,NULL,hInstance, /*the magic pointer*/ this);

// ...

if(uMsg == WM\_CREATE)
{
    // collected here..
    pParent = (CWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
    // .. and then stored for later lookup
    SetWindowLongPtr(hWnd,GWL\_USERDATA,(LONG\_PTR)pParent); 
}
// ...


Du kan også fange meddelelsen WM\_NCCREATE, som foreslået af Moo-Juice.

Og jeg tror ikke, du bør bekymre dig om meddelelserne før - WM\_CREATE, fordi vinduet ikke er helt fuldt initialiseret på det tidspunkt. Hvis du har brug for at indstille tekst, gør du det efter opkaldet til CreateWindow(Ex), det være sig brugerindgang eller et SendMessage opkald.

Andre referencer 1


Den, der opretter vinduet, ejer vinduet 100\%. Hvis du er den, der ringer til CreateWindow (), så kan du bruge GetWindowLong, vel vidende at det er din.


Hvis et bibliotek opretter vinduet, kan du dog ikke fordi det ikke er dit.


(Bortset: Intet stopper nogen fra at træde på andres tæer, men konventionen er ret standard).


Hvis du bruger et bibliotek, der gør dette, vil det generelt have en vis mekanisme til at forbinde dine egne data med et vindue. Selvfølgelig skal du henvise til dokumentationen for det.

Andre referencer 2


Brug Windows egenskaber: SetProp( HWND ,... ), Getprop( HWND ,... ) og RemoveProp( HWND ,... ) [12] [13] [14]

Andre referencer 3


Kan du ikke bruge WNDCLASS.cbWndExtra til at erklære, hvad privat opbevaring din klasse har brug for, og så vil det blive allokeret af Windows, når det opretter et vindue i den klasse.