Шаг 82 - Реализация методов компонента TFolderDialog

Хм. Вообще рассказывать хорошо, но, как кто-то сказал (и теперь очень многие на него ссылаются :)), программисту не нужны комментарии - у него есть текст программы. Так это конечно, но все же я откомментирую нижеследующий текст, то есть листинг:

//----------------------------------
#define NO_WIN32_LEAN_AND_MEAN
#include <shlobj.h>
#include <vcl.h>
#pragma hdrstop

#include "FolderDialog.h"
#pragma package(smart_init)
//----------------------------------
// ValidCtrCheck is used to assure that 
// the components created do not have
// any pure virtual functions.
//

static inline void ValidCtrCheck(TFolderDialog *)
{
	new TFolderDialog(NULL);
}
//----------------------------------
__fastcall TFolderDialog::TFolderDialog(TComponent* Owner)
	: TCommonDialog(Owner)
{
}
int __stdcall FolderBrowseProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)
{
if (!lpData)return 0;
TFolderDialog* dialog = (TFolderDialog*)lpData;
dialog->FHandle = hwnd;
if (uMsg == BFFM_SELCHANGED)
{
	char buf[MAX_PATH];
	SHGetPathFromIDList(LPITEMIDLIST(lParam),buf);
	if (dialog->FOnFolderChanged)
		dialog->OnFolderChanged(dialog, buf);
}
else
if ((uMsg == BFFM_INITIALIZED)&&(dialog->FOnShow))
	dialog->OnShow(dialog);

return 0;
};
//----------------------------------
bool __fastcall TFolderDialog::Execute(void)
{
BROWSEINFO bi;
setmem(&bi, sizeof(bi), 0);
bi.hwndOwner = NULL;
bi.lpszTitle = Title.c_str();
bi.lpfn = FolderBrowseProc;
bi.lParam = (long)this;

int flags = 0;
	if(FOptions.Contains(fdBrowseForComputer))
		flags|=BIF_BROWSEFORCOMPUTER;
	if(FOptions.Contains(fdBrowseForPrinter))
		flags|=BIF_BROWSEFORPRINTER;
	if(FOptions.Contains(fdDontGoBelowDomain))
		flags|=BIF_DONTGOBELOWDOMAIN;
	if(FOptions.Contains(fdReturnOnlySysAncestors))
		flags|=BIF_RETURNFSANCESTORS;
	if(FOptions.Contains(fdReturnOnlySysDirs))
		flags|=BIF_RETURNONLYFSDIRS;
	if(FOptions.Contains(fdStatusText))
		flags|=BIF_STATUSTEXT;
bi.ulFlags = flags;
LPITEMIDLIST lst = SHBrowseForFolder(&bi);
FHandle = 0;
if(FOnClose)
	OnClose(this);
if(!lst)
	return false;
char buf[MAX_PATH];
SHGetPathFromIDList(lst,buf);
FFolder = buf;
return true;
}
//----------------------------------
void __fastcall TFolderDialog::SetStatusText(AnsiString text)
{
FStatusText = text;
if(Handle)
::SendMessage(Handle,BFFM_SETSTATUSTEXT,NULL,(long)text.c_str());
}
//----------------------------------
void __fastcall TFolderDialog::SetFolder(AnsiString folder)
{
if(Handle)
::SendMessage(Handle,BFFM_SETSELECTION,TRUE,(long)folder.c_str());
}
//----------------------------------
void __fastcall TFolderDialog::SetOkEnabled(bool enabled)
{
FOkEnabled = enabled;
enabled = (enabled)?(TRUE):(FALSE);
if(Handle)
::SendMessage(Handle,BFFM_ENABLEOK,NULL,enabled);
}
//----------------------------------
namespace Folderdialog
{
	void __fastcall PACKAGE Register()
	{
		TComponentClass classes[1] = {__classid(TFolderDialog)};
		RegisterComponents("Samples", classes, 0);
	}
}
//----------------------------------

Хы. А кто говорил, что будет легко? Но, на мой взгляд, это самый полнофункциональный вариант использования этой функции шела. Надо сказать, здесь я не стал использовать отдельно функции преобразования списков идентификаторов. Каркас реализации - тот же, что и при прямом использования функции, который мы обсуждали в прошлых шагах. Он виден в реализации функции Execute. Единственная ремарка. Функции (а соответственно и свойства StatusText, Folder, OkEnabled) работают только при наличии открытого диалога. Поэтому их можно использовать в обработчиках событий, но никак не до инициализации.

Вобщем-то честно говоря, код не самый сложный, вполне можно разобраться... Так что разбирайтесь.

А. Самое главное. Чтобы установить компонент, дважды щелкните по значку проекта пакета. Откроется следующее окно:

gif/82_1.gif (6784 b)

Жмем Compile, а потом Install. И наслаждаемся результатом своей работы...


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Аванесов Самвел - 07.09.2002