Soyez le premier à donner votre avis sur cette source.
Vue 8 265 fois - Téléchargée 350 fois
#define _WIN32_WINNT 0x0501 #define _WIN32_IE 0x0501 #include <windows.h> HINSTANCE g_hInst; HWND g_hWnd, g_hListbox; char g_szAppName[] = "DropDown"; BOOL g_bCapture = FALSE; WNDPROC defListboxProc; #define MAX_ITEMS 10 int __fastcall bnatoi(const char* psz) { __asm { xor eax, eax push ebx xor edx, edx xor ebx, ebx cmp byte ptr[ecx], '-' jne short L1 inc ecx mov edx, 0xFFFFFFFF L1: mov bl, byte ptr[ecx] cmp bl, '0' jb short L2 cmp bl, '9' ja short L2 lea eax, dword ptr[eax + 4 * eax] sub bl, '0' add eax, eax inc ecx add eax, ebx jmp short L1 L2: add eax, edx pop ebx xor eax, edx } } LRESULT ListBox_OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam) { POINT pt = {LOWORD(lParam), HIWORD(lParam)}; RECT clientRect, screenRect; POINT screenMousePos; GetCursorPos(&screenMousePos); GetWindowRect(hWnd, &screenRect); GetClientRect(hWnd, &clientRect); LRESULT l = 0; if(PtInRect(&screenRect, screenMousePos)) { if(pt.x > clientRect.right) { // Clic dans la fenêtre, mais en dehors de la zone client // Donc sur la scollbar g_bCapture = TRUE; // Car la ListBox va recevoir WM_CAPTURECHANGED, mais il ne faut pas la fermer // On enlève temporairement la capture ReleaseCapture(); l = CallWindowProc((WNDPROC)GetWindowLongPtr(hWnd, GWL_WNDPROC), hWnd, WM_NCLBUTTONDOWN, HTVSCROLL, MAKELPARAM(screenMousePos.x, screenMousePos.y)); SetCapture(hWnd); g_bCapture = FALSE; } return l; } else DestroyWindow(hWnd); // Clic à coté de la fenêtre return 0; } LRESULT ListBox_OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam) { int sel, count; POINT pt; RECT rect; pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam); GetClientRect(hWnd, &rect); if(PtInRect(&rect, pt) || (wParam & MK_LBUTTON)) { // On prend les mouvements de la souris quand on est au dessus de la listBox, // ou quand le bouton gauche de la souris est enfoncé if(pt.y < 0) PostMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0); if(pt.y > rect.bottom) PostMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0); sel = LOWORD(SendMessage(hWnd, LB_ITEMFROMPOINT, 0, lParam)); SendMessage(hWnd, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, sel)); count = (int)SendMessage(hWnd, LB_GETCOUNT, 0, 0); if(sel != count - 1) SendMessage(hWnd, LB_SELITEMRANGE, FALSE, MAKELPARAM(sel + 1, count - 1)); } return 0; } LRESULT CALLBACK ListboxProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { int sel; switch(uMsg) { case WM_MOUSEMOVE: return ListBox_OnMouseMove(hWnd, wParam, lParam); case WM_LBUTTONDOWN: return ListBox_OnLButtonDown(hWnd, wParam, lParam); case WM_KEYDOWN: switch(wParam) { case VK_DOWN: sel = (int)SendMessage(hWnd, LB_GETSELCOUNT, 0, 0); SendMessage(hWnd, LB_SETSEL, 1, sel); break; case VK_UP: sel = (int)SendMessage(hWnd, LB_GETSELCOUNT, 0, 0); SendMessage(hWnd, LB_SETSEL, 1, sel - 1); SendMessage(hWnd, LB_SETSEL, 0, sel - 1); break; case VK_RETURN: goto ok; case VK_ESCAPE: DestroyWindow(hWnd); break; } break; case WM_LBUTTONUP: ok: case WM_CAPTURECHANGED: if(!g_bCapture) { DestroyWindow(hWnd); g_hListbox = 0; } } return CallWindowProc(defListboxProc, hWnd, uMsg, wParam, lParam); } LRESULT CALLBACK AppWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HWND hEdit; switch(uMsg) { case WM_KEYDOWN: case WM_MOUSEWHEEL: if(g_hListbox) PostMessage(g_hListbox, uMsg, wParam, lParam); break; case WM_CREATE: hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", 0, WS_VISIBLE | WS_CHILD, 0, 0, 200, 25, hWnd, (HMENU)1000, g_hInst, 0); CreateWindowEx(0, "Button", "Test", WS_VISIBLE | WS_CHILD, 200, 0, 100, 25, hWnd, (HMENU)1001, g_hInst, 0); break; case WM_COMMAND: if(LOWORD(wParam) == 1001) { char szitems[32]; GetWindowText(hEdit, szitems, 32); int nItems = bnatoi(szitems); if(nItems < 1) return 0; POINT pt = {200, 25}; // Coordonnées dans la fenêtre mère // Comme on va mettre le bureau en fenêtre mère, il faut transformer les coordonnées MapWindowPoints(hWnd, HWND_DESKTOP, &pt, 1); g_hListbox = CreateWindowEx(WS_EX_TOOLWINDOW, "Listbox", 0, WS_VSCROLL | WS_BORDER | LBS_HASSTRINGS | LBS_MULTIPLESEL |WS_VISIBLE | WS_CHILD, pt.x, pt.y, 100, 100, hWnd, 0, g_hInst, 0); int height = (int)SendMessage(g_hListbox, LB_GETITEMHEIGHT, 0, 0); if(nItems > MAX_ITEMS) height *= MAX_ITEMS; else height *= nItems; SetWindowPos(g_hListbox, 0, 0, 0, 100, height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); SetParent(g_hListbox, HWND_DESKTOP); for(int i = 0; i < nItems; i++) SendMessage(g_hListbox, LB_ADDSTRING, 0, (LPARAM)"Chaine d'exemple"); // Donne le focus à la fenêtre principale, pour qu'elle puisse rediriger les // message vers la listbox (WM_KEYDOWN, WM_WOUSEWHEEL...) SetFocus(hWnd); SetCapture(g_hListbox); defListboxProc = (WNDPROC)SetWindowLongPtr(g_hListbox, GWL_WNDPROC, (LONG_PTR)ListboxProc); } break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } #ifdef _DEBUG int main() #else #pragma comment(linker, "/entry:myWinMain") int __stdcall myWinMain() #endif { MSG msg; g_hInst = GetModuleHandle(0); WNDCLASSEX wcex; memset(&wcex, 0, sizeof wcex); wcex.cbSize = sizeof wcex; wcex.lpfnWndProc = AppWndProc; wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.hInstance = g_hInst; wcex.lpszClassName = g_szAppName; wcex.hbrBackground = GetSysColorBrush(COLOR_WINDOW); wcex.hCursor = LoadCursor(0, IDC_ARROW); if(!RegisterClassEx(&wcex)) return 1; g_hWnd = CreateWindowEx(0, g_szAppName, g_szAppName, WS_OVERLAPPED | WS_VISIBLE | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, g_hInst, 0); if(!g_hWnd) return 1; ShowWindow(g_hWnd, SW_NORMAL); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } #ifdef _DEBUG return (int)msg.wParam; #else ExitProcess(msg.wParam); #endif }
met sa valeur sur la pile pour restituer en sortie de fonction.
Aller dur forum asmfr pour le reste, ça évitera de flooder cette source avec des questions sans rapport au sujet principal.
J'suis chiant je sais ;)
__declspec(naked) int __fastcall bnatoi(char *szsrc)
{ // ECX = szsrc
__asm {
xor edx, edx
mov [esp-4], ebx
mov dl, [ecx]
xor eax, eax
xor ebx, ebx
cmp dl, '-'
jb short nbrEXIT
jne short noPOINT
inc ecx
dec ebx
nbrLOOP:
mov dl, [ecx]
noPOINT:
cmp dl, '0'
jb short nbrSTOP
cmp dl, '9'
ja short nbrSTOP
lea eax, [eax+eax*4]
sub dl, '0'
add eax, eax
inc ecx
add eax, edx
jmp short nbrLOOP
nbrSTOP:
add eax, ebx
xor eax, ebx
nbrEXIT:
mov ebx, [esp-4]
ret 0
}
}
lea peut faire addition, soustraction et multiplication en 1 passe.
donc: lea eax, [eax+eax*4]
fait: eax = eax * 5;
WM_KEYDOWN & WM_MOUSEWHEEL sont deux messages utiles qui ne sont pas envoyés à la ListBox car elle n'a pas le focus, et on ne peut pas le lui donner
Je me doute que ecx contient le param, qu'est ce que ca pourrait être d'autre...
Je précise que c'est BruNews qui a écrit cette fonction, pas moi
Maintenant que tu sais ce que contient ecx, tu va peut être mieux comprendre
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.