|
open을 선택하면 뜨는 open dialogbox아시죠 제가 그 dialog와 같은 걸 만들어야하는데...
왜 새로 만드냐면 file명 말고 몇가지 정보를 더 입력받아서 file을 create해야 하걸랑요
그래서 newsgroup을 좀 뒤져보니까 누가 다음에 올린 것 처럼하면 open dialog의 combobox를
맹글 수 있다고 하더라구요 그래서 열심히 copy & paste하고 <shlobj.h>를 include한 후
컴파일을 했더니
multiple declaration 'FVSHOWINFO"....등등 <shlobj.h>를 포함하면 중복됐다고 error가 나는거여요
제가 뭘 잘못했을까요? ㅜ_ㅜ
open dialog box의 확장판은 어쩔 수 없이 imp님이 갈켜준데로 vcl을 건드려서 맹글 수 밖에 없는걸까요?
// in header...
TImageList *ImageList1;
void __fastcall FillWithCSIDL(int CSIDL, bool SubItems);
void __fastcall DoFillList(LPSHELLFOLDER lpsf, LPITEMIDLIST lpidl);
// in source...
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
// Bind to the system image list
SHFILEINFO IconInfo;
ImageList1 = new TImageList(this);
ImageList1->Handle = SHGetFileInfo("", 0, &IconInfo, sizeof(IconInfo),
SHGFI_ICON | SHGFI_SMALLICON |
SHGFI_SYSICONINDEX);
ImageList1->ShareImages = true;
// fill the combobox
FillWithCSIDL(CSIDL_DRIVES, true);
}
void __fastcall TForm1::FillWithCSIDL(int CSIDL, bool SubItems)
{
// Get a pointer to the shell's IMalloc interface
// for later use -- it's required to use the shell
// task allocator to free the Item identifiers and PIDLs.
LPMALLOC lpMalloc;
if (SUCCEEDED(SHGetMalloc(&lpMalloc)))
{
// Grab a pointer to the root (desktop) folder
LPSHELLFOLDER lpsf;
if (SUCCEEDED(SHGetDesktopFolder(&lpsf)))
{
// Get the piddle of the virtual folder
LPITEMIDLIST lpidlSpecial;
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL,
&lpidlSpecial)))
{
SHFILEINFO FileInfo;
unsigned int uSHFlags = SHGFI_SYSICONINDEX |
SHGFI_DISPLAYNAME |
SHGFI_ATTRIBUTES |
SHGFI_PIDL;
// get file info
SHGetFileInfo(reinterpret_cast<LPCSTR>(lpidlSpecial),
0, &FileInfo, sizeof(SHFILEINFO),
uSHFlags);
ComboBox1->Items->Add(FileInfo.szDisplayName);
ComboBox1->Items->Objects[ComboBox1->Items->Count - 1] =
reinterpret_cast<TObject *>(FileInfo.iIcon);
if (SubItems)
{
// Bind the shell folder to the virtual
// folder's piddle (LPITEMIDLIST)
LPSHELLFOLDER lpsfSpecial;
if (SUCCEEDED(lpsf->BindToObject(lpidlSpecial, NULL,
IID_IShellFolder,
reinterpret_cast<void **>
(&lpsfSpecial))))
{
// call the DoFillList() member function
DoFillList(lpsfSpecial, lpidlSpecial);
lpsfSpecial->Release();
}
}
}
// clean up
lpMalloc->Free(lpidlSpecial);
lpsf->Release();
}
// clean up
lpMalloc->Release();
}
}
// PIDL "piddle" helper routine
LPITEMIDLIST GetNextItem(LPITEMIDLIST pidl)
{
unsigned short nLen = pidl->mkid.cb;
if (nLen == 0) return NULL;
return reinterpret_cast<LPITEMIDLIST>
(reinterpret_cast<LPBYTE>(pidl) + nLen);
}
// PIDL "piddle" helper routine
unsigned short GetPIDLSize(LPITEMIDLIST lpidl)
{
unsigned short cb = 0;
while (lpidl)
{
cb = static_cast<unsigned short>(cb + lpidl->mkid.cb);
lpidl = GetNextItem(lpidl);
}
return static_cast<unsigned short>(cb + 2);
}
// PIDL "piddle" helper routine
LPITEMIDLIST MergeIDLists(LPITEMIDLIST lpidl1, LPITEMIDLIST lpidl2)
{
int cb1, cb2;
if (lpidl1) cb1 = GetPIDLSize(lpidl1);
if (cb1) cb1 = cb1 - 2;
if (lpidl2) cb2 = GetPIDLSize(lpidl2);
if (cb2) cb2 = cb2 - 2;
int total_size = cb1 + cb2 + 2;
LPMALLOC lpMalloc;
LPITEMIDLIST lpidlNew;
if (SUCCEEDED(SHGetMalloc(&lpMalloc)))
{
lpidlNew =
reinterpret_cast<LPITEMIDLIST>(lpMalloc->Alloc(total_size));
lpMalloc->Release();
}
if (lpidlNew)
{
ZeroMemory(lpidlNew, total_size);
CopyMemory(lpidlNew, lpidl1, cb1);
CopyMemory(reinterpret_cast<LPBYTE>(lpidlNew) + cb1, lpidl2, cb2);
FillMemory(reinterpret_cast<LPBYTE>(lpidlNew) + cb1 + cb2, 2, 0);
return lpidlNew;
}
return NULL;
}
// FillList to fill the ComboBox with icons / display names
void __fastcall TForm1::DoFillList(LPSHELLFOLDER lpsf, LPITEMIDLIST lpidl)
{
// Get a pointer to the shell's IMalloc interface
// for later use -- it's required to use the shell
// task allocator to free the Item identifiers and PIDLs.
LPMALLOC lpMalloc;
if (SUCCEEDED(SHGetMalloc(&lpMalloc)))
{
// Here we enumerate the contents of the folder that
// lpsf is bound to. To do this, we first grab a pointer
// to the IEnumIDList interface.
LPENUMIDLIST lpeidl;
if (SUCCEEDED(lpsf->EnumObjects(NULL, SHCONTF_FOLDERS |
SHCONTF_NONFOLDERS, &lpeidl)))
{
// prevent screen updating
ComboBox1->Items->BeginUpdate();
// Using the IEnumIDList interface's Next() method, we
// iterates through the item IDs one at a time. The resulting
// item is stored in lpidlCurrent.
LPITEMIDLIST lpidlCurrent;
while (lpeidl->Next(1, &lpidlCurrent, NULL) == S_OK)
{
// create a fully qualified itemidlist
LPITEMIDLIST lpidlFQ = MergeIDLists(lpidl, lpidlCurrent);
if (lpidlFQ)
{
SHFILEINFO FileInfo;
unsigned int uSHFlags = SHGFI_SYSICONINDEX |
SHGFI_DISPLAYNAME |
SHGFI_PIDL;
// get file info
SHGetFileInfo(reinterpret_cast<LPCSTR>(lpidlFQ),
0, &FileInfo, sizeof(SHFILEINFO),
uSHFlags);
ComboBox1->Items->Add(FileInfo.szDisplayName);
int index = ComboBox1->Items->Count - 1;
ComboBox1->Items->Objects[index] =
reinterpret_cast<TObject *>(FileInfo.iIcon);
// free the fullly qualified itemidlist
lpMalloc->Free(lpidlFQ);
}
// free lpidlCurrent filled by the Next() method
lpMalloc->Free(lpidlCurrent);
}
// restore screen updates
ComboBox1->Items->EndUpdate();
// release the pointer to the IEnumIDList interface
lpeidl->Release();
}
// release the pointer to the IMalloc interface
lpMalloc->Release();
}
}
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control, int Index,
TRect &Rect, TOwnerDrawState State)
{
AnsiString text = ComboBox1->Items->Strings[Index];
int IconIndex =
reinterpret_cast<int>(ComboBox1->Items->Objects[Index]);
if (State.Contains(odSelected))
{
ComboBox1->Canvas->Brush->Color = clHighlight;
ComboBox1->Canvas->Font->Color = clHighlightText;
ImageList1->DrawingStyle = dsSelected;
}
else
{
ComboBox1->Canvas->Brush->Color = ComboBox1->Color;
ComboBox1->Canvas->Font->Color = ComboBox1->Font->Color;
ImageList1->DrawingStyle = dsNormal;
}
ComboBox1->Canvas->FillRect(Rect);
if (Index > 0) Rect.Left = Rect.Left + 16;
ImageList1->Draw(ComboBox1->Canvas, Rect.Left, Rect.Top,
IconIndex, true);
Rect.Left = Rect.Left + ImageList1->Width + 5;
ComboBox1->Canvas->TextRect(Rect, Rect.Left + 1, Rect.Top + 1, text);
}
void __fastcall TForm1::ComboBox1MeasureItem(TWinControl *Control,
int Index, int &Height)
{
Height = ImageList1->Height + 4;
}
|