Skocz do zawartości

okna dialogowe


Onyx

Recommended Posts

Witam
Rozumiem że chodzi o dialog wywoływany za pomocą GetOpenFileName lub
GetSaveFileName jeżeli tak to:
Struktura OPENFILENAME ma pole LPOFNHOOKPROC lpfnHook; . W tym polu podajesz adres nowej procedurki obsługi dialogu i wszystkie kontrolki możesz obsługiwać tak jakby były przez Ciebie utworzone. Resztę sprawdź w helpie. Jeżeli jednak nie zrozumiesz tego to mogę ci napisać przykład ale w MASM jażeli będziesz zainteresowany to napisz.
Pozdro

Link do komentarza
Udostępnij na innych stronach

Witam
Napałem przykład niestety w MASM (ale uprzedzałem) mam nadzieję, że to będzie zrozumiałe.

Procedura, którą za pomocą subclassingu zastąpimy standardową procedurę obsługi Dialogu. Musimy korzystać z subclassingu tylko wtedy gdy umieszczamy własne kontrolki na oknie dialogowym i chcemy otrzymywać od nich komunikaty. Jeżeli jednak nie umieszczmy dodatkowych kontrolek to na obsługę już istniejących wystarsza sama procedura OFNHookProc trzeba tylko obsłużyć odpowiednie komunikaty.

NewDialogProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
        .if uMsg==WM_COMMAND
            mov eax, lParam
            .if eax == hNowy
               ;Kliknięto nasz przycisk     
            .endif
        .endif
        ;Przywołaj orginalną procedurae obsługi okna dialogowego
    invoke CallWindowProc, lpOldDialogProc,hWnd,uMsg,wParam,lParam
        ret   
NewDialogProc endp

Procedura obługi dialogu dla Hooka. W przykładzie za pomocą obsługi komunikatu WM_NOTIFY wyświetli MassageBox po zmianie filtra plików. Przy obsłudze WM_INITDIALOG zmieniamy jego rozmiar okna dialogowego, tworzymy dodatkowy przycisk na oknie dialogowym, zmieniamy jego czcionkę. Za pomocą SetWindowLong zmieniamy też procedurę obsługi okna dialogowego (bez tego niemoglibyśmy obsługiwać komunikatów dodatkowego przycisku)

OFNHookProc proc uses esi hDlg:HWND, uiMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hDialog: DWORD
LOCAL hCtrl: DWORD
LOCAL buf[100]:BYTE
LOCAL rect: RECT
        
        .if uiMsg == WM_INITDIALOG
            ;PrintText "WM_INITDIALOG"
            invoke GetParent, hDlg ;Pobierz uchwyt dialogu
        mov hDialog, eax
            invoke GetClientRect,hDialog, addr rect ;Pobierz rozmiar okna
            add rect.right, 100 ;Ziększ szerokość bo musi się zmieścić przycisk ktory dodamy
            invoke SetWindowPos, hDialog, HWND_TOP, 0, 0, rect.right, rect.bottom,SWP_SHOWWINDOW or SWP_NOMOVE
            sub rect.right, 95 ;Obliczamy pozycję 
            ;Tworzymy dodatkowy przycisk
            invoke CreateWindowEx, 0, offset szButton, offset szNowy, WS_CHILD or WS_VISIBLE, rect.right, 40, 80, 20,  hDialog, 0, hInstance, 0
            mov hNowy, eax
            ;Musimy jeszcze zmienić czcionkę przycisku na takąsamą jak dialogu
            invoke SendMessage, hDialog, WM_GETFONT, 0, 0
            invoke SendMessage, hNowy, WM_SETFONT, eax, TRUE 
            ;Zmieniamy procedurę Dialogu aby obsługiwać wszystkie komunikaty
            ;jakie nam się spodobają
            invoke SetWindowLong, hDialog, GWL_WNDPROC, addr NewDialogProc
            mov lpOldDialogProc, eax ;Trzeba zapamiętać adres starej procedury  
        .elseif uiMsg == WM_NOTIFY 
        mov esi, lParam
        assume esi: ptr NMHDR
        .if ([esi].code == CDN_SELCHANGE)  ;czy zmiana filtra
                invoke GetParent, hDlg ;Pobierz uchwyt dialogu
                mov hDialog, eax
                invoke GetDlgItem, hDialog, TYPE_FILTERS_COMBO_FIELD ;Identyfikator ComboBox = 0470h
                mov hCtrl, eax
                invoke SendMessage, eax, CB_GETCURSEL, 0, 0 ;Pobierz index
                mov edx, eax
                invoke SendMessage, hCtrl, CB_GETLBTEXT, edx, addr buf ;Pobierz tekst
                invoke MessageBox, 0, addr buf, addr szAppName, MB_OK  ;Wyświetl komunikat
        .endif
            assume esi: nothing

        .endif
        ret
OFNHookProc endp

No i procedura obsługi okna naszej aplikacji

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
        
        .IF uMsg==WM_DESTROY
                invoke PostQuitMessage,NULL
        .ELSEIF uMsg==WM_CREATE
            ;Wypełnij strukturę OPENFILENAME
            mov ofn.lStructSize, sizeof OPENFILENAME
                mov     eax, hWnd
                mov     ofn.hWndOwner, eax
                mov     ofn.hInstance, 0
                mov     ofn.lpstrFilter, offset szFilter
                mov     ofn.lpstrCustomFilter, 0
                mov     ofn.nMaxCustFilter, 0
                mov     ofn.nFilterIndex, 0
                mov     ofn.lpstrFile, 0                
                mov     ofn.nMaxFile, MAX_PATH
                mov     ofn.lpstrFileTitle, 0 
                mov     ofn.nMaxFileTitle, MAX_PATH
                mov     ofn.lpstrInitialDir, 0
                mov     ofn.lpstrTitle, 0       
                ;Ważne jest: OFN_EXPLORER or OFN_ENABLEHOOK         
                mov     ofn.Flags, OFN_FILEMUSTEXIST or OFN_HIDEREADONLY or OFN_EXPLORER or OFN_ENABLEHOOK
                mov     ofn.nFileOffset, 0
                mov     ofn.nFileExtension, 0
                mov     ofn.lpstrDefExt, 0 
                mov     ofn.lCustData, 0
                mov     ofn.lpfnHook, offset OFNHookProc ;Tu adres nowej procedurki obsługi dialogu
                mov     ofn.lpTemplateName, 0
            ;Utowrz przycisk po kliknięciu ktorego wywołamy OpenDialog
                invoke CreateWindowEx, 0, offset szButton, offset szOpen, WS_CHILD or WS_VISIBLE, 10, 10, 80, 20,  hWnd, 0, hInstance, 0
            mov hBtnOpen, eax
        .ELSEIF uMsg==WM_COMMAND
                mov eax, lParam
                .if eax == hBtnOpen
                   ;Wywołaj Dialog
                   invoke GetOpenFileName, addr ofn
                .endif 
        .ELSE
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam            
                ret
        .ENDIF
        xor eax,eax
        ret
WndProc endp

No tyle myślę, że przytaczanie reszty kodu jest zbędne i bez tego ten post jest wystarczajaco długi :) Gdyby jeszcze coś było niejasne to pytaj.
Pozdro

Link do komentarza
Udostępnij na innych stronach

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gość
Odpowiedz...

×   Wkleiłeś zawartość bez formatowania.   Usuń formatowanie

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Utwórz nowe...