c ++ - Oprettelse af et win32 modalt vindue med CreateWindow

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg opretter et vindue med CreateWindow() og viser det med ShowWindow(). Men det overordnede vindue, som dette blev oprettet på, skal deaktiveres, indtil brugeren vender tilbage fra dette vindue, dvs. det skal simulere modal dialogboks.

Bedste reference


Sørg for at indstille hwndParent i CreateWindow og brug EnableWindow(hwndParent, FALSE) for at deaktivere forælder efter at have vist pop op-vinduet. Derefter aktiveres forældrene med EnableWindow(hwndParent, TRUE) efter popup-vinduet er lukket.

Andre referencer 1


Modalitet, del 1: UI-modalitet vs kode-modalitet forklarer, hvordan man gør dette, og hvorfor du måske ikke vil. [10]

Andre referencer 2


Du skal overveje, hvad det betyder at være et modalt vindue - i princippet er vinduets overordnede deaktiveret. Den eneste automatiske måde at gøre dette på (jeg er opmærksom på) er at ringe DialogBox() for at oprette en modal dialog boks. Da du vil bruge CreateWindow(), så er alt, hvad du skal gøre, manuelt deaktiveret forældrenes vindue manuelt.


Ideelt set ville det være bedre at gå dialogboksen rute (da OS kender præcis hvad der skal gøres for at oprette et modal vindue), men jeg antager, at denne mulighed er der, hvis du skal bruge den.

Andre referencer 3


Du kan også køre en 'sekundær meddelelsessløjfe', som holder forældrenes vindue inaktiv til dit arbejde med dialogboksen 'modal' er færdig.

Andre referencer 4


Okay, jeg har lige kvæget med det samme problem selv. Jeg havde brug for en hurtig dialog, der opførte sig som det ville, hvis jeg brugte DialogBox (), men jeg ønskede ikke at oprette en skabelon til det pågældende projekt, jeg brugte.


Det, jeg opdagede, er, at hvis du deaktiverer dialogen overordnede vinduer, deaktiverer du også dialogen. Og du kan ikke aktivere dialogen uden at genaktivere overordnede dialogboksen. Så den metode vandt ikke.


Jeg har også opdaget, at du ikke kan bruge SetCapture ()/ReleaseCapture (), da dialogenes vinduer ikke får beskeder.


Jeg fandt en løsning, der virker: Brug en lokal meddelelsespumpe, der drives af enten PeekMessage () eller GetMessage (). Her er koden der fungerede for mig:


  while (!m\_bFinished)
  {
     BOOL bEat;

     if (PeekMessage(&msg, NULL, 0, 0, PM\_REMOVE))
     {
        if (msg.message == WM\_CHAR)
        {
           if (msg.wParam == VK\_ESCAPE)
           {
              m\_bFinished = TRUE;
              continue;
           }
        }

        bEat = FALSE;

        if (msg.message >= WM\_MOUSEFIRST &&
           msg.message <= WM\_MOUSELAST)
        {
           RECT rectMe;

           pcMe->GetWindowRect(&rectMe);
           if (!::PtInRect(&rectMe, msg.pt))
              bEat = TRUE;
        }

        if (!bEat)
        {
           ::TranslateMessage(&msg);
           ::DispatchMessage(&msg);
        }
     }
  }


Hvad dette effektivt betyder, er at 'spise' eventuelle musemeddelelser, der ligger uden for klientområdet i vinduet for alle meddelelser, der leveres til den pågældende applikation. Det forbydes ikke at klikke uden for applikationen, bare klikke hvor som helst inden for applikationen, der ikke er i klientområdet i vinduet 'modal'. Hvis du tilføjer en MessageBeep (), når du spiser en besked, får du den samme adfærd som en reel modal dialog.


m\_bFinished er et BOOL-medlem af klassen, og det bliver indstillet, hvis enten OK eller Annuller knapperne er tilgængelige på 'dialogboksen' og under visse andre forhold uden for kodestykket her.