Skocz do zawartości

Burn

Członkowie
  • Postów

    0
  • Dołączył

  • Ostatnio

    Nigdy

Posty napisane przez Burn

  1. Witam
    Jeżeli główne okno ma odpowiadającą Ci czcionkę to najprosćiej jest probrać za pomocą komunikatu WM_GETFONT uchwyt czcionki głownego okna i wysłać komunikat WM_SETFONT do Twojej kontrolki Tab.
    Jeżeli chcesz stworzyć własna czcionkę to służą do tego funkcje:
    CreateFont i CreateFontIndirect do usunięcia czcionki (gdy już nie będzie potrzebna) użyj DeleteObject
    Pozdro

  2. Dzięki, już sobie poradziłem :) Wszystko działa :) Napisałem (w MASM) to tak:

    To jest kod modułu ping.inc

    include wsock32.inc
    includelib wsock32.lib
    
    PingInit PROTO
    PingClean PROTO
    Ping PROTO :DWORD,:DWORD,:DWORD,:WORD
    
    .const   
        ECHO_PACKET_SIZE            equ 32 ;rozmiar pakietu danych
                   
        PING_INIT_OK                equ 0
        PING_INIT_ERROR_LOADLIB     equ 1
        PING_INIT_ERROR_GETPROCADDR equ 2
        PING_INIT_ERROR_WSASTARTUP  equ 3
       
        PING_INVALID_HOSTNAME       equ -1
       
    .data
       
        szIcmp            db "icmp.dll",0
        szIcmpCreateFile  db "IcmpCreateFile",0
        szIcmpCloseHandle db "IcmpCloseHandle",0
        szIcmpSendEcho    db "IcmpSendEcho",0
    
    .data?
        
        hIcmp             dd ?
        lpIcmpCreateFile  dd ?
        lpIcmpCloseHandle dd ?
        lpIcmpSendEcho    dd ?         
    
    .code
    
    PingInit proc 
    LOCAL wsa: WSADATA
              
            invoke LoadLibrary, offset szIcmp
            cmp eax, 0
            je errorloadlib
            mov hIcmp, eax
            
        invoke GetProcAddress, hIcmp, offset szIcmpCreateFile
        cmp eax, 0
        je errorgetprocaddr
        mov lpIcmpCreateFile, eax
        
        invoke GetProcAddress, hIcmp, offset szIcmpCloseHandle
        cmp eax, 0
        je errorgetprocaddr
        mov lpIcmpCloseHandle, eax
        
        invoke GetProcAddress, hIcmp, offset szIcmpSendEcho
        cmp eax, 0
        je errorgetprocaddr
        mov lpIcmpSendEcho, eax
        
        invoke WSAStartup, 0101h, addr wsa
        cmp eax, 0
        jne errorwsastartup
        sub eax, eax
        ret
        errorwsastartup:
        inc eax ;eax = 3 Error PING_INIT_ERROR_WSASTARTUP
        errorgetprocaddr:
        push eax
        invoke FreeLibrary, hIcmp
        pop eax
        inc eax ;eax = 2 Error PING_INIT_ERROR_GETPROCADDR
        errorloadlib:    
        inc eax ;eax = 1 Error PING_INIT_ERROR_LOADLIB
            ret
                  
    PingInit endp
    
    PingClean proc
            
            invoke WSACleanup
            invoke FreeLibrary, hIcmp
            ret
    
    PingClean endp
    
    Ping proc uses esi lpAddr:DWORD, lpEcho:DWORD, lpOptions:DWORD, TimeOut:WORD
    LOCAL addrIP: DWORD
    LOCAL hIcmpFile: DWORD
    LOCAL acPingBuffer[ECHO_PACKET_SIZE]: BYTE
            
    
             invoke inet_addr, lpAddr
             mov addrIP, eax
             
             .if eax == INADDR_NONE
                    invoke gethostbyname, lpAddr
                    .if eax == 0  
                        dec eax ;eax = -1 PING_INVALID_HOSTNAME                     
                    ret
                    .endif
                    mov eax, dword ptr [eax + 12]
                    mov eax, dword ptr [eax]
                    mov eax, dword ptr [eax]
                    mov addrIP, eax
             .endif 
                     
             invoke RtlFillMemory, addr acPingBuffer, ECHO_PACKET_SIZE, 0AAh
             
             call lpIcmpCreateFile
             mov hIcmpFile, eax
                     
             mov esi, lpEcho
             assume esi: ptr ICMP_ECHO_REPLY
             lea eax, acPingBuffer
             mov [esi].DataPointer, eax
             mov [esi].DataSize, ECHO_PACKET_SIZE
             assume esi: nothing
             
             push TimeOut
             push sizeof ICMP_ECHO_REPLY + ECHO_PACKET_SIZE
             push lpEcho
             push lpOptions
             push ECHO_PACKET_SIZE
             lea  eax, acPingBuffer
             push eax
             push addrIP
             push hIcmpFile
             call lpIcmpSendEcho
             
             push eax
             
             push hIcmpFile
             call lpIcmpCloseHandle 
             
             pop eax                 
             ret
    
    Ping endp
    

    Najpierw wywołuję funkcję PingInit, później Ping i odpowiednio formatuję dane które podaję/otrzymuję no i po wszystkim PingClean.
    Parametry funkcji Ping to:
    lpAddr - adres lub nazwa hosta
    lpEcho - adres zmiennej typu ICMP_ECHO_REPLY (zwraca potrzebne mi informacje)
    lpOptions - adres zmiennej typu ICMP_OPTIONS (tu podaję niektóre dane np. TTL)
    TimeOut - max. czas odpowiedzi
    Wydaje mi się że wszystko działa poprawnie, gdyby jednak ktos zauważył jakiś błąd to proszę o wyjaśnienie co i dlaczego jest źle.
    Pozdrawiam

  3. Witam
    Może i to dość proste, jednak ja nigdy nie zajmowalem sie programowaniem aplikacji sieciowych przy użyciu WinApi. Czy ktoś może podać przykład jak napisać (oczywiście w WinApi) funkcję która zwróci te informacjie co komenda Ping (W takiej lub podobnej postaci) z tym, że chcę mieć dostęp do poszczególnych zawartych tam informacji. Dobrze by było gdyby można podać nazwę lub adres IP.
    Pozdro

  4. Witam
    Okno (a nawet jego określony obszar) możesz odrysować za pomocą funkcji InvalidateRect (ewentualnie InvalidateRgn) którą byś musiał wywołać po każdej operacji po której okno wymagałoby odświezenia.
    Zastanawiam sie nad tym w jaki sposób wyświetlasz bitmapy, ale chyba na w obsłudze komunikatu WM_PAINT. Radzę wszyskie operacje rysowania, wyświetlania bitmap wykonywać właśnie w po wywołaniu przez system tego komunikatu (WM_PAINT), wtedy pobierasz za pomocą BeginPaint uchwyt device context okna ktore wymaga odrysowania następnie malujesz po oknie (wyświetlasz bitmapy) i po tym wszystkim wywołujwsz EndPaint.
    Pozdro

  5. Witam
    Nie bardzo wiem o co chodzi :/ Czu chodzi tylko o odczytanie wersji programu czy faktycznie o wydobycie z pliku zasobów typu RT_VERSION . Jeżeli chcesz tylko uzyskać informacje o wersji trzeba użuć funkcji GetFileVersionInfo przykład jest tutaj:)
    Pozdro

  6. Witam
    Czy nie chodzi Ci przypadkiem o PropertySheet czyli Dialog na którym znajduje się SysTabControl32( na którego zakładkach możesz wyświetlać okna dialogowe) i posiadający Buttony OK, Anuluj, Zastosuj . Czyli po prostu taki dialog na który dobrze nadaje się jako okno ustawień programu :/
    Jeżeli tak to proponuję poszukać w google właśnie pod hasłem PropertySheet Jeżeli nie znajdziesz nic ciekawego to napisz jak będę miał czas to napisze jutro (dzisiaj nie mam czasu) przykład (tylko pewnie w MASM) :)
    Pozdro

  7. Witam
    Kod w porządku :) W kontrolce EDIT powinno pojawić się 3298 (tak jak napisałem bez separatora dziesiętnego). Jeżeli kontrolka EDIT nie wyświetla tekstu to winne za to mogą być nieprawidłowy uchwyt hKalk lub nieprawidłowy ID kontrolki 502. Pomijam już to, że z niewiadomych przyczyn używasz EM_REPLACESEL do wyświetlenia tekstu w EDIT zamiast WM_SETTEXT lub SetWindowText. Chyba, że rzeczywiście chcesz zmieniać zaznaczony tekst. W każdym razie podany kod powinien dzialać chyb, że popełniłeś jeden ze wspomnianych błedów (ew. oba na raz).
    Pozdro

  8. Witam
    O jakie procesy chodzi :/ Może o usługi systemów NT :/ , jeżeli tak to nie wiem dokładnie bo mam Win 98 ale chyba trzeba by coś pokombinować z funkcjami OpenSCManager, OpenService, SetServiceStatus ale nic więcej na ten temat nie wiem bo nie mam na czym z tym poeksperymentować.
    Pozdro

  9. Nie no nie zalamuj się. To mój pierwszy program w C++ ale wcześniej z WinApi korzystałem w Delphi i MASM.
    Co do ksiązek o WinApi to najbardziej znana jest Charles Petzold "Programowanie Windows" niestety dotyczy ona tylko GUI. Nie znam niestety polskiej ksiązki w której były by opisane funkcje dotyczące procesów.

  10. Witam
    Nie na pisałeś z czym już kombinowałeś i jak tworzysz ten BUTTON. Nie sprawdziłem ale może spróbuj CreateWindowEx a w pierwszym parametrze podając WS_EX_TRANSPARENT (reszta parametrów jak CreateWindow). Nie wiem też co chcesz uzyskać czy chodzi o zwykłą zmianę koloru tła czy on musi być koniecznie przezroczysty np. po to aby nie przykrywał obrazka tła.
    Pozdro

  11. Witam
    Nie wydaje mi się, aby były to jakieś drastyczne zmiany. Co najwyżej dojdą nowe funkcje, a to przecież pozytywna zmiana :) Wydaje mi się, że M$ nie może wprowadzić zbyt dużych zmian, ponieważ na tym systemie muszą (a przynajmniej powinny) się też uruchamiać programy napisane pod starsze systemy (kompatybilność wstecz). Więc wydaje mi się, że nie ma powodów do obaw.
    Pozdro

  12. Witam
    Napisałem przykład :D To mój pierwszy program w C++ wiec proszę się nie śmiać jak coś namieszałem :P Jest to program, który zamyka Gadu-Gadu (Tlena nie mam).
    Program był kompilowany pod Dev-C++ 4.9.9.0 i sprawdzony na Win 98 ale wydaje mi się że powinien też działać na Win XP. :)

    #include <windows.h>
    #include <tlhelp32.h>
    
    int main(void) {
        
        HANDLE hSnapshot = NULL;
        //Uzyskaj uchwyt migawki systemu
        hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        PROCESSENTRY32 ProcInfo; //W tej zmiennej bedziemy otrzymywać info o procesach       
        ZeroMemory(&ProcInfo, sizeof(ProcInfo)); //Wyczyść strukturę PROCESSENTRY32
        ProcInfo.dwSize = sizeof(ProcInfo);      //Zapisz jej rozmiar
        Process32First(hSnapshot, &ProcInfo); //Pierwszy Proces
        
        DWORD GGProcID = 0; //Nowa zmienna do przzechowywania ID Procesu
        do {   
        //Szukamy Gadu-Gadu. Zwróć uwagę na  podwójny "\" w ścieżce   
        if (lstrcmpi(ProcInfo.szExeFile, "C:\\Program Files\\Gadu-Gadu\\GG.EXE") == 0) {
            GGProcID = ProcInfo.th32ProcessID; //Zapisz ID Procesu
            break; //Przerwij - po co dalej szukać jak już znaleźliśmy :)
        }
        } while (Process32Next(hSnapshot, &ProcInfo)); //Następny uruchomiony proces
        CloseHandle(hSnapshot); //Zamklnij uchwyt 
    
        if (!GGProcID) { //Czy ID Procesu to 0
           //Wyświetl komunikat
           MessageBox(0, "Nie znaleziono Gadu-Gadu", NULL, MB_ICONERROR); 
           return 0; //Zwróć 0
        }
        HANDLE hGGProc = NULL; //Uchwyt procesu
        //Trzeba otworzyć proces z proces aby uzyskać prawa do jego zakończenia 
        if (!(hGGProc = OpenProcess(PROCESS_TERMINATE, FALSE, GGProcID))) {
        //Wyświetl komunikat
        MessageBox(0, "Błąd OpenProcess. Nie udało się uzyskać praw do zamknięcia.", 
                    NULL, MB_ICONERROR); 
        return 0;//Zwróć 0
        }  
        TerminateProcess(hGGProc, 0); //Zakończ proces
        CloseHandle(hGGProc); //Zamknij uchwyt
        //Zwróć 1
        return 1;
    
    }
    

    W przykładzie dla uproszczenia założyłem, że CreateToolhelp32Snapshot nie zwróci błedu i Process32First też się powiedzie (najprawdopodobniej w systemie jest uruchomiony conajmniej 1 proces). Ale jeżeli wykorzystujesz go w "normalnym" programie to oczywiście musisz liczyć się z możliwością wystąpienia błedu.
    Mam nadzieję, że Ci pomoże. Gdyby coś jeszcze było niejasne to pytaj.
    Pozdro

  13. Witam
    Niestety nie znam metody by robić to automatycznie (za pomocą styli) :( ale można sobie napisać funkcję, która posortuje elementy listy. :) 
    Po dodaniu każdego (oczywiście jeżeli dodajemy jednoczesnie dużą liczbę elementów to robimy to tylko po dodaniu wszystkich) elementu do listy trzeba wywołać:

                    ;jeżeli wParam = 0 sortowanie rosnące, 1 malejące
                    ;lParam to adres funkcji sortującej 
                    invoke SendMessage,hLView, LVM_SORTITEMS, 0, addr LVSortProc
    

    Funkcja sortująca może być np. taka:

    LVSortProc proc lParam1: LPARAM, lParam2: LPARAM, lParamSort: LPARAM
    LOCAL szBuff1[256]:BYTE
    LOCAL szBuff2[256]:BYTE
    LOCAL lvi:LV_ITEM
        
        ;Wypełnij struktrę LV_ITEM
        mov     lvi.imask, LVIF_TEXT
        mov     lvi.cchTextMax, 256
            mov     lvi.iSubItem, 0 
        lea     eax, szBuff1
        mov     lvi.pszText, eax    
            ;Pobierz teksty do porownania
        invoke  SendMessage, hLView, LVM_GETITEMTEXT, lParam1, addr lvi
        lea     eax, szBuff2 
        mov     lvi.pszText, eax       
        invoke  SendMessage, hLView, LVM_GETITEMTEXT, lParam2, addr lvi
        ;Porwnaj teksty (ignorując wielkość liter)       
        invoke  lstrcmpi, addr szBuff1, addr szBuff2   
        .if lParamSort == 1 ;Jeżeli chcemy sortować malejąco
            neg eax         ;trzeba zmienić znak wyniku porwnania na przeciwny
        .endif
            ret
    
    LVSortProc endp
    

    Oczywiście funkcja w tej postaci zawsze sortuje elementy wg. tekstu Item (pierwszej kolumny) ale można ją przerobić tak, aby sortowała wg. dowolnego SubItem (dowolnej kolumny). Myślę, że jeżeli będziesz miał potrzebę sortowania według kolumn to z tym już sobie poradzisz, ale jeżeli jednak nie to napisz.
    Pozdro

  14. Witam
    Cieszę się, że się przydało :D
    Niestety nie wiem, dlaczego źle interpretuje akurat to. Zrobiłem nawet sobie z ciekawości przykładową funkcję gdzie parametrami były kolejno 2 byte, 2 word, 2 dword i wszystko Ok (na stos rzeczywiście jest wrzucony dword przynajmniej tak pokazuje dissasembler). Być może wina leży w tym, że wsprintf ma nie określoną liczbę argumentów.
    Pozdro

  15. Witam
    1. No właśnie chodziło mi o to, że flaga LVFI_NEARESTXY dziala tylko przy stylach LVS_SMALLICON i LVS_ICON. Więc dlatego zwraca Ci -1. Aby szukać pozycji najbliższej kursora musisz napisać własną procedurę jednak ja tego nigdy nie robiłem (nie miałem potrzeby) więc Ci nie podpowiem jak. Natomiast jeżeli chcesz znaleźć tylko pozycję zawierającą określony ciąg znaków (string) to jest proste trzeba tylko ustawić pola struktury LV_FINDINFO .flags na LVFI_STRING lub LVFI_PARTIAL i .psz na adres szukanego ciagu znaków (przy LVFI_STRING musisz podać cały natomiast przy LVFI_PARTIAL wystarszy tylko początek) Póżniej wystarczy tylko wywołać:

    ktory=ListView_FindItem(hListView,-1, &znajdz);
    

    2. Kiedyś w MASM na swoje potrzeby napisałem taką funkcję. Jeżeli nie bedziesz umiał tego przetłumaczyć na C++ to gdzieś poczytaj o LVM_GETITEM
    Parametry:
    hListView: HWND - uchwyt ListView
    iItemNo: DWORD - Numer Item (czyli wiersza)
    iSubItemNo: DWORD - Numer SubItem (czyli kolumny)
    lpText: LPSTR - Adres buforka w którym będzie zwrócony tekst
    MaxLen: DWORD - Maksymalna długość zwracenego tekstu (naie więcej niż długosć bufora)
    Uwaga: Wiersze i kolumny numerowane są od 0

    GetListViewText proc hListView: HWND, iItemNo: DWORD, iSubItemNo: DWORD, lpText: LPSTR, MaxLen: DWORD
        LOCAL lvi:LV_ITEM       
            
            push iItemNo
            pop  lvi.iItem
            push iSubItemNo
            pop  lvi.iSubItem
            mov  lvi.imask, LVIF_TEXT
            push lpText
            pop  lvi.pszText
            push MaxLen
            pop  lvi.cchTextMax
            invoke SendMessage, hListView, LVM_GETITEM, 0, addr lvi 
            ret
    
    GetListViewText endp
    

    3. Niestety tu jest problem ponieważ wywołanie Dialogu za pomocą DialogBoxParam lub makra DialogBox tworzy modalne okno dialogowe, co uniemożliwia wywołnie drugiego dialogu spróbuj użyć CreateDialogParam albo makra CreateDialog (parametry bez zmian). Powinno działać :P
    4.
    Składnia:
    CONTROL text, id, class, style, x, y, width, height [, extended-style]
    text - tekst kontrolki
    id - identyfikator
    class - klasa
    x, y - pozycja kontrolki względem głownego okna
    width - szerokość
    height - wysokość
    extended-style - styl rozszerzony (parametr opcjonalny)

    Jak z tego wynika pole text pozostawiasz bez zmian (przecież kontrolka nie ma wyświetlać tekstu tylko bitmapę). Aby wyświetlić bitmapę trzeba za pomocą funkcji LoadBitmap załadowąc bitmapę z zasobów a następnie trzeba wysłać komunikat STM_SETIMAGE do kontrolki którego wParam to IMAGE_BITMAP (chcemy załadować bitmapę) a lParam to uchwyt bitmapy. W MASM można to zrobić tak:

            invoke LoadBitmap, hInstance, ID_BITMAPY
            invoke SendDlgItemMessage, hWnd, ID_KONTROLKI, STM_SETIMAGE, IMAGE_BITMAP, eax 
    

    Ale się rozpisałem :) Mam nadzieję, że przynajmniej trochę pomogłem.
    Uwaga Post został zmodyfikowany (dokładnie 3 punkt) bo tam wcześniej napisałem takie bzdury, że wstyd się przyznawać... :$
    Pozdro

  16. Witam
    Problem nie tkwi w samej funkcji wsprintf a w sposobie przekazywania parametrów. Kompilator spodziewa się argumentu 32 bitowego (dword) a otrzymuje 16 bitowy (word). Dlatego uzupełnia to sobie w niezbyt mądry sposób przez dodanie push 0 pomiędzy argumentami. Aby pozbyć się prolemu można napisać tak:

                sub eax, eax ;lepiej  wyzerować rejestr
                mov ax, STime.wYear ;zapisz word do rejeestru ax
                push eax    ;teraz idzie dword na stos jak oczekuje kompilator    
                mov ax, STime.wMonth
                push eax        
                mov ax, STime.wDay
                push eax
                mov ax, STime.wMinute
                push eax                
                mov ax, STime.wHour
                push eax        
                lea eax, templateData
                push eax        
                lea eax, fsBuf
                push eax
                call wsprintf
    

    Myślę ,że to lepsze od Twojego obejścia problemu a taksamo działa :P
    Pozdro

  17. Witam
    1. Czy napewno chcesz szukać item najbliższy od aktulnej pozycji kursora tak :/ Jeżeli tak to jak styl ma Twój ListView bo w MSDN piszą, że flaga LVFI_NEARESTXY działa tylko przy durzych i małych ikonach.
    2. Nazwy z sąsiednich kolumn :/ Chodzi o nagłówki listy, czy o zawartość sąsiednich kolumn listy (SubItem)
    3. Jak wywołujesz drugi dialog :/ Jeżeli np. po naciśnięciu na przycisk to powinno działać w ten sposób, że każdy dialog ma osobną procedurę z tym ,że w wywołaniu idrogiego dialogu za pomocą DialogBoxParam musisz ustawić trzeci parametr hWndParent (uchwyt rodzica) na uchwyt dialogu pierwszego.
    4. O co chodzi z tą Bitmapą :/ Chcesz wyświetlić bitmapę na dialogu? Można by to zrobić w obsłudze komunikatu WM_PAINT ale to jest bardziej skomplikowane znacznie prościej jest utworzenie na dialogu kontrolki Static ze stylem SS_BITMAP i jeżeli bitmapa znajduje sie w zasobach to załadować ją za pomocą LoadBitmap, natomiast jeżeli bitmapa znajduje się w pliku to trzeba użyć LoadImage.
    To wszystko co mogę teraz napisać, napisz bardziej szczegółowo pytania na, które nie dostałeś satysfakcionującej odpowiedzi.
    Pozdro

  18. Witam
    Jeżeli piszesz program graficzny to wydaje mi się, że chwili gdy użytkownik zacznie używać jakiegoś narzędzia musisz zapisać do bufora aktualny obraz.
    Jeżeli chcesz mieć możliwość cofania np. 10 razy to musisz utworzyć sobie 10 elementową tablicę buforków i w chwili operacji odpowiednio zmieniać miejscami elementy tablicy i nadpisywać ostatni buffor w tablicy.
    Pozdro

  19. 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

×
×
  • Utwórz nowe...