PDA

Visualizza la versione completa : [C - Win32] EnumWindows e trasparenza


JackInTheBox
19-09-2008, 19:37
Ciao a tutti,
sto attualmente realizzando, a puro scopo "ludico", un banale programmetto in C che visualizzi la propria icona sulla task bar per permettere di accedere alla sua configurazione, e che si occupa di ciclare con EnumWindows gli handle presenti (scartandone alcuni), e rendendoli quindi semi-trasparenti.

E qui arriva il "problema": il ciclo per eseguire ininterrottamente EnumWindows è piuttosto pesante, ed anche realizzando un porting della DoEvents le cose sembrano non migliorare.
Sapete aiutarmi?

Ecco il codice interessato:



void DoEventsLoop(){
MSG message;
while(PeekMessage(&message, NULL, 0, 0, PM_REMOVE)){
DispatchMessage(&message);
}
}

BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam){

if (IsWindowVisible(hwnd) && (hwnd!=shellTray) && IsWindow(hwnd) && (hwnd!=deskhWnd) && (hwnd!=foreWin)){
SetWindowLong(hwnd, GWL_EXSTYLE,GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
m_pSetLayeredWindowAttributes(hwnd, 0, 100, LWA_ALPHA);
}
DoEventsLoop();

return TRUE;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
switch(uMsg){
case WM_COMMAND:

if (lParam == WM_LBUTTONUP){
DestroyWindow(hwnd);
PostQuitMessage(0);
}

break;

default:
break;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

void CreateInvisibleWindow(){
wcx.cbSize = sizeof(wcx);
wcx.lpfnWndProc = WndProc;
wcx.hInstance = myInst;
wcx.hIcon = LoadIcon(myInst, IDI_APPLICATION);
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wcx.lpszClassName = "myWin";

RegisterClassEx(&wcx);
hidWin=CreateWindowEx(0, "myWin", "glassWin",
WS_OVERLAPPEDWINDOW&~WS_MAXIMIZEBOX&~WS_THICKFRAME,
0, 0, 278, 178, 0,0, myInst,0);

ShowWindow(hidWin,SW_HIDE);
UpdateWindow(hidWin);
}


int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
myInst = hInstance;
CreateInvisibleWindow();
ShowTrayIcon(hidWin);

HINSTANCE hUser32 = LoadLibrary("user32.dll");
m_pSetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes)GetProcAddress(hUs er32, "SetLayeredWindowAttributes");
FreeLibrary(hUser32);

deskhWnd = GetDesktopWindow();
shellTray = FindWindow("Shell_TrayWnd","");


while(1){
foreWin = GetForegroundWindow();
EnumWindows(MyEnumWindowsProc, 0);

DoEventsLoop();

SetWindowLong(foreWin, GWL_EXSTYLE,
GetWindowLong(foreWin, GWL_EXSTYLE) | WS_EX_LAYERED);
m_pSetLayeredWindowAttributes(foreWin, 0, 255, LWA_ALPHA);
}

return TRUE;
}


In parole povere (e come prevedibile), il ciclo while(1){ } mi "uccide" il processore, portandolo anche al 50% delle propria possibilità. :dhò:

Anticipatamente grazie a tutti.

oregon
19-09-2008, 20:46
Aggiungi nel loop una

Sleep(20);

JackInTheBox
19-09-2008, 21:25
Ciao Oregon, e grazie per la risposta.
Avevo già tentato questa strada, con un lag maggiore (150 ms). Ho effettivamente notato un miglioramento per quanto riguarda i carichi del processore, ma al tempo stesso la cosa si è tradotta in un peggioramento delle prestazioni dell'applicazione (rendering più lento).

Pensi che quello dello Sleep() sia l'unico percorso?

oregon
19-09-2008, 22:53
Usa un valore minore di 150 per la Sleep (come ti dicevo 20, o anche 15) ...

E' importante che il thread "si addormenti" un po' per evitare il fatto che il carico del processore schizzi al 100%.

Ma deve essere un tempo limitato per evitare i problemi di lentezza del rendering.

Loading