Не могу перевести демку по работе SHBrowseForFolder с C++ на ассемблер... Помогите ламеру!!!

Тема в разделе "WASM.WIN32", создана пользователем Oleg_SK, 9 ноя 2004.

  1. Oleg_SK

    Oleg_SK Guest

    Публикаций:
    0
    Привет всем!

    Ребята мне очень неудобно обращаться к вам с такой просьбой, но другого выхода (за разумное время) у меня нет...

    Есть две функции, написанные на C++. Они показывают: как нужно использовать функцию SHBrowseForFolder в своих программах. Я попробовал перевести их на ассемблер, но у меня ничего не получилось. Удалось перевести только первую функцию и ~50% кода второй (да и то, пока не знаю правильно или нет) и все - я застрял... Кое-что из смутившего меня я, кажется, примерно представляю, как сделать в теории, но на практике этого сделать не получается, т.к. я быстро запутался в одном заголовочном файле (у меня маленький опыт копания в них). А некоторые вещи я вообще не представляю, как реализовать. В общем, помогите, кто может! Переведите эти функции на ассемблер! SOS!!!

    Ниже я привожу тексты этих двух функций. Кое-где я сделал свои комментарии:



    **********************************************************

    #include <windows.h>

    #include <atlbase.h>

    #include <shlobj.h>

    #pragma comment(lib,"shell32")



    static int CALLBACK

    BrowseCallbackProc (HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)

    {

    TCHAR szPath[_MAX_PATH];

    switch (uMsg) {

    case BFFM_INITIALIZED:

    if (lpData)

    SendMessage(hWnd,BFFM_SETSELECTION,TRUE,lpData);

    break;

    case BFFM_SELCHANGED:

    SHGetPathFromIDList(LPITEMIDLIST(lParam),szPath);

    SendMessage(hWnd, BFFM_SETSTATUSTEXT, NULL, LPARAM(szPath));

    break;

    }

    return 0;

    }



    BOOL GetFolder (LPCTSTR szTitle, LPTSTR szPath, LPCTSTR szRoot, HWND hWndOwner)

    {

    if (szPath == NULL)

    return false;



    bool result = false;



    LPMALLOC pMalloc;

    if (::SHGetMalloc(&pMalloc) == NOERROR) {

    BROWSEINFO bi;

    ::ZeroMemory(&bi,sizeof bi);

    bi.ulFlags = BIF_RETURNONLYFSDIRS;



    // дескриптор окна-владельца диалога

    bi.hwndOwner = hWndOwner;



    // добавление заголовка к диалогу

    bi.lpszTitle = szTitle;



    // отображение текущего каталога

    bi.lpfn = BrowseCallbackProc;

    bi.ulFlags |= BIF_STATUSTEXT;



    // установка каталога по умолчанию

    bi.lParam = LPARAM(szPath);



    // установка корневого каталога

    if (szRoot != NULL) {

    IShellFolder *pDF;

    if (SHGetDesktopFolder(&pDF) == NOERROR) {

    LPITEMIDLIST pIdl = NULL;

    ULONG chEaten;

    ULONG dwAttributes;



    USES_CONVERSION; //Эту и следующую строчку я вообще незнаю как реализовать...

    LPOLESTR oleStr = T2OLE(szRoot);



    pDF->ParseDisplayName(NULL,NULL,oleStr,&chEaten,&pIdl,&dwAttributes);

    pDF->Release();



    bi.pidlRoot = pIdl;

    }

    }



    LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi);

    if (pidl != NULL) {

    if (::SHGetPathFromIDList(pidl,szPath))

    result = true;

    pMalloc->Free(pidl);

    }

    if (bi.pidlRoot != NULL)

    pMalloc->Free(bi.pidlRoot);

    pMalloc->Release();

    }

    return result;

    }



    Прототип нашей функции может выглядеть следующим образом:



    BOOL GetFolder(LPCTSTR szTitle,LPTSTR szPath,LPCTSTR szRoot=NULL,HWND hWndOwner=NULL);



    **********************************************************









    Так теперь показываю, что я всетаки перевел сам (тут, скорее всего, есть куча ошибок):



    **********************************************************

    BrowseCallbackProc proc hWnd:lol: WORD, uMsg:lol: WORD, wParam:lol: WORD, lParam:lol: WORD

    mov eax, uMsg

    .if eax==BFFM_INITIALIZED

    .if lParam

    invoke SendMessage, hWnd, BFFM_SETSELECTION, TRUE, lParam

    .endif

    .elseif eax==BFFM_SELCHANGED

    invoke SHGetPathFromIDList, lParam, offset FullPath

    invoke SendMessage, hWnd, BFFM_SETSTATUSTEXT, NULL, offset FullPath

    .endif

    xor eax, eax

    ret

    BrowseCallbackProc endp



    GetFolder proc LPCTSTR szTitle, LPTSTR szPath, LPCTSTR szRoot, HWND hWndOwner

    LOCAL result:lol: WORD

    LOCAL pMalloc:lol: WORD

    LOCAL bi:BROWSEINFO

    LOCAL pDF:lol: WORD

    LOCAL pIdl:lol: WORD

    LOCAL chEaten:lol: WORD

    LOCAL dwAttributes:lol: WORD



    mov result, 0



    .if !szPath

    xor eax, eax

    ret

    .endif



    invoke SHGetMalloc, addr pMalloc

    .if eax==NOERROR

    invoke ZeroMemory, addr bi, sizeof(bi)

    mov bi.ulFlags, BIF_RETURNONLYFSDIRS





    mrm bi.hwndOwner, hWndOwner





    mrm bi.lpszTitle, szTitle





    mov bi.lpfn, offset OpenFolderProc

    or bi.ulFlags, BIF_STATUSTEXT;





    mrm bi.lParam, szPath



    ;

    ; .if szRoot

    ; invoke SHGetDesktopFolder, addr pDF

    ; .if eax==NOERROR

    ; mov pIdl, NULL

    ;

    ; .endif

    ; .endif



    invoke SHBrowseForFolder, addr bi

    mov pIdl, eax

    .if eax

    invoke SHGetPathFromIDList pIdl, szPath

    .if eax

    mov result, TRUE

    .endif

    mov eax, pMalloc

    mov eax, [eax+IMalloc.Free] ; Это только в теории...

    push pIdl

    call eax

    .endif

    .endif

    GetFolder endp



    P.S: Это нужно не для домашнего задания! Мне просто самому интересно... Да и код - стандартный - IMHO, многим пригодится.



    P.P.S: Прошу прощение, за то что не использую тэги...
     
  2. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    У компилятора включи генерацию ассемблерного листинга...
     
  3. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Код (Text):
    1. .DATA?
    2. sBuf db 512 dup (?)
    3.  
    4. .CODE
    5. bifCB PROC hWnd:DWORD,uMsg:UINT,wParam:DWORD,lParam:DWORD
    6.    .IF uMsg == BFFM_INITIALIZED
    7.       .IF lParam
    8.          invoke PostMessage,hWnd,BFFM_SETSELECTION,1,lParam
    9.       .ENDIF
    10.    .ENDIF
    11.    ret
    12. bifCB ENDP
    13.  
    14. GetFolder proc LPCTSTR szTitle, LPTSTR szPath, LPCTSTR szRoot, HWND hWndOwner
    15.    push hWndOwner
    16.    pop DWORD PTR [sBuf]                     ; hwndOwner
    17.    and DWORD PTR [sBuf + 4],0               ; pidlRoot
    18.    and DWORD PTR [sBuf + 8],0               ; pszDisplayName
    19.    push szTitle
    20.    pop DWORD PTR [sBuf + 12]                ; lpszTitle
    21.    mov DWORD PTR [sBuf + 16],BIF_STATUSTEXT ; ulFlags
    22.    mov DWORD PTR [sBuf + 20],OFFSET bifCB   ; lpfn
    23.    push szPath
    24.    pop DWORD PTR [sBuf + 24]                ; lParam
    25.    and DWORD PTR [sBuf + 28],0              ; iImage
    26.    invoke SHBrowseForFolder,OFFSET sBuf
    27.    test eax,eax
    28.    jz @err
    29.    invoke SHGetPathFromIDList,eax,szPath
    30. @err:
    31.    ret
    32. GetFolder endp


    Осталось только добавить pMalloc->Free(pidl);

    Хмм... Об этом уже писали в форуме.
     
  4. Oleg_SK

    Oleg_SK Guest

    Публикаций:
    0
    Привет всем!



    semen

    Да, я знаю о такой возможности, но на момент создания этого поста у меня не было (и сейчас пока еще нет) соответствующего компилятора... Хотя у кого-то из знакомых я видел MS Visual Studio v6.0, надо будет поискать.



    Quantum

    При написании программы я использовал почти такой же код... Причем совершенно забыл про pMalloc->Free(pidl).

    Спасибо, что напомнил.

    Я просил перевести этот С++-шный код потому что он показывает как можно более полно использовать возможности диалога открытия папки. К примеру, он демонстрирует следующее:

    * Установка дескриптора окна-владельца диалога.

    * Добавление заголовка к диалогу.

    * Отображение текущего каталога.

    * Установка каталога по умолчанию.

    * Установка корневого каталога.

    Я не вижу причин не использовать эти возможности.

    Этот код я взял из статьи Игоря Ткачева, "Как выдать окно выбора каталога?" на RSDN.

    Я уже стал подумывать: а не бросить ли мне эту затею? Тем более, что я подсмотрел как для этой цели можно использовать диалог выбора файла (а он гораздо симпатичнее и проще в использовании)...



    Всем большое спасибо!
     
  5. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    привет! на тебе раб. пример - мучай его ;)

    хотел вчера кинуть - так инет нам выключили (змеи) :)

    1. диалогом выбора файла нельзя выбрать директорию (по-моему)

    2. процедурой обработки сообщений можно творить с окном че хочешь, но поток сообщений туда ограничен: я лепил чекбокс на окне и обрабатывал сообщение о выборе директории, однако если его значение менять после ее выбора - то значение получалось неверное. хотя, вероятно, я испробовал не все ;)



    [​IMG] 706301455__seldir.zip
     
  6. Oleg_SK

    Oleg_SK Guest

    Публикаций:
    0
    shoo





    Да, это действительно так. В общем, я тоже так думаю. Но, как то раз (в ответе на вопрос №5049), в субскрайбовской рассылке по ассемблеру, один из ее экспертов (Gibbel) сказал, что некоторые умельцы сумели ее для этого приспособить. С тех пор я ищу пример этого... На днях смотрел утилитку Zidrav и, вроде бы, в ней именно так и было по идее сделано. По этому я и обрадовался. Я решил, что диалог выбора файла позволяет выбрать (если указать имя вручную) еще не существующий файл. Но сейчас попробовал это сделать, но у меня ничего не вышло. Видимо это ошибка в той утилитке.



    За аттач спасибо, сейчас гляну...
     
  7. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine


    наверно нужно флаг указать, что можно указывать несущ файлы - ща не могу глянуть - сисю переустанавливаю (задрала)
     
  8. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Снять флаги OFN_FILEMUSTEXIST и OFN_PATHMUSTEXIST.
     
  9. Oleg_SK

    Oleg_SK Guest

    Публикаций:
    0
    shoo

    Quantum

    Спасибо за инфу. Буду знать. Автор вышеуказанной утилитки видимо забыл сбросить эти флаги, поэтому там эта фича не работает.
     
  10. Oleg_SK

    Oleg_SK Guest

    Публикаций:
    0
    shoo

    Тогда получается, что в некоторых случаях, если немного по извращаться, то диалог выбора папки все-таки можно заменить на диалог открытия файла. Например, это можно сделать в моем случае: мне диалог выбора папки нужен для выбора папки, в которой будет создан новый файл. Вызывается этот диалог при нажатии на кнопку, закрепленную за полем ввода. После выбора папки, путь к ней помещается в это поле ввода. Причем это поле ввода может заполняться и автоматически при выборе открываемого файла. Сделано это для удобства, чтобы новый файл по умолчанию создавался в той же папке, в которой находится открываемый файл. Теперь посмотрим, как в этом случае можно заменить диалог выбора папки на диалог выбора файла. Для этого просто меняем задачу поля ввода: теперь оно будет содержать не путь к папке, а путь к еще не существующему файлу. Первоначально этот путь будет генерироваться автоматически, после того как пользователь выберет открываемый файл. А далее, если он решит изменить папку, в которой будет создан новый файл, он нажмет соответствующую кнопку и ему будет выдан диалог выбора файла, но фишка в том, что поле имени файла уже будет заполнено по умолчанию значением из поля ввода и юзеру останется указать только новую папку... Ну а в том случае, если перед этим поле ввода еще не будет заполнено, то юзеру помимо папки придется указать и имя файла… Вот вроде бы и все.