Avatar billede mortenah Nybegynder
19. januar 2004 - 10:46 Der er 9 kommentarer

Lille fiks wait-funktion

Jeg har brug for at lave en funktion i en regular dll der ikke laver andet end at vente (ikke busy waiting) indtil brugeren kører med/trykker på musen eller bruger tastaturet.

Baggrunden for dette er en applikation udviklet i et ikke windowssprog der sluger 100% processortid når det kører. Fra dette program kan man dog godt kalde dll-funktioner, derfor ideen med at lade det kalde en c++ funktion der simpelthen går i sleep indtil brugeren reagerer.

Hvordan gøres dette smartest???
Avatar billede bertelbrander Novice
19. januar 2004 - 17:51 #1
Jeg tror ikke at det kan gøres smart eller at der kan laves en "lille fix wait funktion".

Det hurtige metode var at lave en lille funktion der kalder Sleep(10) hver gang den bliver kaldt.

Man kunne også kikke på PeekMessage(), eller en kombination af GetKeyboardState() og GetCursorPos() alle i kombination med Sleep().

Men elegant tror jeg ikke det kan blive.
Avatar billede mortenah Nybegynder
20. januar 2004 - 10:20 #2
Jeg har spekuleret i at lave et "usynligt" vindue eller dialog, hvor man så bare kunne vente på WM_MOUSEMOVE, WM_KEYDOWN osv...

Men hvordan laver man et sådan usynligt vindue der modtager alle message inputs???
Avatar billede bertelbrander Novice
20. januar 2004 - 19:15 #3
Jeg tror ikke du skal begynde at lave usynlige vinduer og fange diverse beskeder for det, jeg tror at du vil få problemer med at få sendt beskederne videre til den rigtige applikation.

Du kan måske bruge SetWindowsHookEx(...) til at instalere en hook til at rode i køen af beskeder til din applikation:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp

Man kunne også sætte prioriteten på den tråd hvori applikationen kører ned til et passende level, så den ikke stjæler alt tiden fra de andre applikationer.
Avatar billede mortenah Nybegynder
22. januar 2004 - 09:54 #4
Det lader til ideen med at bruge hooks er det rigtige, men jeg har stadig nogle problemer. Efter at funktionen har installeret en hook skal den jo vente indtil hooken rent faktisk kaldes (SE KODE). Hvordan gøres dette? Jeg har kigget lidt på MsgWaitForMultipleObjectsEx funktionen, men kan ikke få det til at virke ordentligt. Nogen ideer?

HINSTANCE hins=NULL;
HHOOK hkb=NULL;

// hook callbackfunktionen, der kører ved tryk på tastaturet
RESULT __declspec(dllexport)__stdcall  CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
        // Her skal calmdown funktionen (der jo "sover") signaleres om at fortsætte.. HOWTO?

    LRESULT RetVal = CallNextHookEx( hkb, nCode, wParam, lParam );   
    return  RetVal;
}

BOOL installhook()
{
        hins=AfxGetInstanceHandle();
    hkb=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hins,0);
    return TRUE;
}

void removehook()
{
        UnhookWindowsHookEx(hkb);
}

// Dette er funktionen der kaldes fra det eksterne program når det skal falde i søvn
// (i dette eks.) indtil tastaturet bruges
_declspec(dllexport)void calmdown()
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
        installhook();
        // Her skal funktionen SOVE indtil KeyboardProc funktionen kaldes.. HOWTO???
        removehook();
}
Avatar billede bertelbrander Novice
23. januar 2004 - 00:40 #5
Du burde kunne lave en semphore:
Semaphore = CreateSemaphore(0, 0, 1000, "Whatever");

Og så vente på den i calmdown():
WaitForSingleObject(Semaphore, INFINITE);

Og frigive semaphoren i din hook procedure:
ReleaseSemaphore(Semaphore, 1, 0);

Jeg kan ikke få hooken til at virke, så jeg har ikke testet.
Avatar billede mortenah Nybegynder
23. januar 2004 - 18:04 #6
Jeg har brugt netop denne fremgangsmåde (dog med en CreateEvent i stedet).

Problemet er bare at når den står og venter på at eventen bliver sat, kan hooken ikke køre da den ligger i samme process.

:(
Avatar billede bertelbrander Novice
23. januar 2004 - 20:33 #7
Måske kan du lave en tread (med CreateThread()) til at have hooken i?
Avatar billede mortenah Nybegynder
25. januar 2004 - 19:57 #8
Løsnigen er ufattelig enkel:

extern "C" __declspec(dllexport) void easynow()
{
  MSG msg ;
  if (GetMessage(&msg,NULL,0,0))
  {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
  }
}

Det var ellers noget af det første jeg prøvede, men nu virker det altså. Men så lærte jeg da både om hooks og tråde... :)
Avatar billede bertelbrander Novice
25. januar 2004 - 22:57 #9
Hvis det virker, ja, så er det let og ligetil.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester