· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

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

Посл.отвђт Сообщенiе


Дата: Ноя 9, 2004 12:53:44 · Поправил: Oleg_SK

Привет всем!
Ребята мне очень неудобно обращаться к вам с такой просьбой, но другого выхода (за разумное время) у меня нет...
Есть две функции, написанные на 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:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
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:DWORD
LOCAL pMalloc:DWORD
LOCAL bi:BROWSEINFO
LOCAL pDF:DWORD
LOCAL pIdl:DWORD
LOCAL chEaten:DWORD
LOCAL dwAttributes:DWORD

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: Прошу прощение, за то что не использую тэги...


Дата: Ноя 10, 2004 12:54:32

У компилятора включи генерацию ассемблерного листинга...


Дата: Ноя 10, 2004 15:54:13 · Поправил: Quantum

.DATA?
sBuf db 512 dup (?)

.CODE
bifCB PROC hWnd:DWORD,uMsg:UINT,wParam:DWORD,lParam:DWORD
   .IF uMsg == BFFM_INITIALIZED
      .IF lParam
         invoke PostMessage,hWnd,BFFM_SETSELECTION,1,lParam
      .ENDIF
   .ENDIF
   ret
bifCB ENDP

GetFolder proc LPCTSTR szTitle, LPTSTR szPath, LPCTSTR szRoot, HWND hWndOwner
   push hWndOwner
   pop DWORD PTR [sBuf]                     ; hwndOwner
   and DWORD PTR [sBuf + 4],0               ; pidlRoot
   and DWORD PTR [sBuf + 8],0               ; pszDisplayName
   push szTitle
   pop DWORD PTR [sBuf + 12]                ; lpszTitle
   mov DWORD PTR [sBuf + 16],BIF_STATUSTEXT ; ulFlags
   mov DWORD PTR [sBuf + 20],OFFSET bifCB   ; lpfn
   push szPath
   pop DWORD PTR [sBuf + 24]                ; lParam
   and DWORD PTR [sBuf + 28],0              ; iImage
   invoke SHBrowseForFolder,OFFSET sBuf
   test eax,eax
   jz @err
   invoke SHGetPathFromIDList,eax,szPath
@err:
   ret
GetFolder endp

Осталось только добавить pMalloc->Free(pidl);
Хмм... Об этом уже писали в форуме.


Дата: Ноя 17, 2004 04:08:52

Привет всем!

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

Quantum
При написании программы я использовал почти такой же код... Причем совершенно забыл про pMalloc->Free(pidl).
Спасибо, что напомнил.
Я просил перевести этот С++-шный код потому что он показывает как можно более полно использовать возможности диалога открытия папки. К примеру, он демонстрирует следующее:
* Установка дескриптора окна-владельца диалога.
* Добавление заголовка к диалогу.
* Отображение текущего каталога.
* Установка каталога по умолчанию.
* Установка корневого каталога.
Я не вижу причин не использовать эти возможности.
Этот код я взял из статьи Игоря Ткачева, "Как выдать окно выбора каталога?" на RSDN.
Я уже стал подумывать: а не бросить ли мне эту затею? Тем более, что я подсмотрел как для этой цели можно использовать диалог выбора файла (а он гораздо симпатичнее и проще в использовании)...

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


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.065