線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:4597
推到 Plurk!
推到 Facebook!

在BCB中包含shlobj.h出现重命名的问题以及如何呼叫一个目录对&#35805

尚未結案
bigdogchina
版主


發表:238
回覆:523
積分:312
註冊:2003-04-28

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-06-26 21:19:39 IP:211.162.xxx.xxx 未訂閱
大大们好,弟弟我又有问题了 大多专业软件在要求输入目录的编辑框旁都放了一个按钮,点击后打开一个目录窗口,我也想在程式中实现这个功能.实现这个功能要调用Windows API函数SHBrowseForFolder,完整声明为WINSHELLAPI LPITEMIDLIST WINAPI SHBrowseForFolder(LPBROWSEINFO lpbi),返回一个ITEMIDLIST类型的指针,通过这个指针调用函数SHGetPathFromIDList可以确定所选择的目录的全名称.入参为BROWSEINFO结构的指针.要使用SHBrowseForFolder的时候,不包含shlobj.h则该函数未定义,包含了shlobj.h则有一大堆东西重定义。请问具体怎么回事? 我在网路上找了半天,发现有两种办法来解决: 第一种:
#define NO_WIN32_LEAN_AND_MEAN   //必须放在#include 之前
#include 
#include 
这样编译能通过. 第二种:将FVSHOWINFO改为FVSHOWINFOA,然后保存shlobj.h! 呀,整个世界清净了! 可是我觉得很奇怪的是:在BCB5自带的例子\CBuilder5\Examples\WinTools中也同样用到了目录对话框,可是为什么它又没有加shlobj.h,而只在最前面用了 #define NO_WIN32_LEAN_AND_MEAN 我现在思路很凌乱,不知道怎么一会事 还有该如何实现一个目录对话框呢?能不能给个例子看看,大大们,又劳您们废心解答了,谢谢!!! 人生在勤,不索何获?
------
人生在勤,不索何获?
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-06-26 22:54:02 IP:61.224.xxx.xxx 未訂閱
//---------------------------------------------------------------------------
#define NO_WIN32_LEAN_AND_MEAN    #include 
#include  // for GlobalFreePtr()
#pragma hdrstop    #include "Unit1.h"
//----------------------------------------------------------------------------//
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//----------------------------------------------------------------------------//
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
}
//----------------------------------------------------------------------------//    void __fastcall TForm1::Button1Click(TObject *Sender)
{
    // 以下取自 WinTools 之 TDump1.cpp
    // Use Windows 95 Directory box to get dir
    String WorkDir;
    BROWSEINFO bi;
    char WDir[MAX_PATH];
    char FolderName[MAX_PATH];
    LPITEMIDLIST ItemID;        memset(&bi, 0, sizeof(BROWSEINFO));
    memset(WDir, 0, MAX_PATH);
    bi.hwndOwner = Handle;
    bi.pszDisplayName = FolderName;
    bi.lpszTitle = "Select Working Directory!";
    ItemID = SHBrowseForFolder(&bi);
    SHGetPathFromIDList(ItemID, WDir);
    GlobalFreePtr(ItemID);
    WorkDir = String(WDir);
    ShowMessage(WorkDir);
}
//----------------------------------------------------------------------------//    
沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-06-27 00:58:08 IP:218.173.xxx.xxx 未訂閱

Fix compiler errors in shellapi.h or shlobj.h

http://www.bcbdev.com/faqs/faq91.htm Answer You may encounter compiler errors in the API header files shellapi.h and shlobj.h if you try to include them from a BCB5 VCL program. The problem is caused by conflicts between the API header files, and the VCL header files shlobj.hpp and shellapi.hpp. The HPP version of the files exist for the sake of other VCL headers (ie you should never need to include shlobj.hpp or shellapi.hpp in your code). The solution to shellapi.h and shlobj.h compiler errors is to globally define the constant NO_WIN32_LEAN_AND_MEAN in your project. You can do this in the IDE from the Directories/Conditionals tab of the project options dialog. Enter NO_WIN32_LEAN_AND_MEAN in the Conditional Defines box. If you have multiple defines listed, you can separate them with semicolons. If you compile from the commandline, you can define NO_WIN32_LEAN_AND_MEAN inside your makefile, or by passing it to make with the -D switch. You can also use the -D switch if you compile directly with bcc32. You might be tempted to define NO_WIN32_LEAN_AND_MEAN by placing a #define statement right in the source file that needs shlobj.h or shellapi.h. Like this:
#include 
#pragma hdrstop    #define NO_WIN32_LEAN_AND_MEAN
#include 
Unfortunately, this won't help. NO_WIN32_LEAN_AND_MEAN must be defined before you include vcl.h. To understand why, look at the files vcl0.h and shlobj.hpp. Since NO_WIN32_LEAN_AND_MEAN must be defined before including vcl.h, you could try this:
#define NO_WIN32_LEAN_AND_MEAN
#include 
#pragma hdrstop    #include 
This will solve the compiler errors, but it will also disrupt your use of precompiled header files. As a result, your project will take longer to compile. For information on why, see the article on precompiled header use. Since you can't use a local #define to solve the problem, you are forced to define NO_WIN32_LEAN_AND_MEAN globally in your project options or makefile. While this will solve your problems regarding shlobj.h, it does come at a cost. Defining NO_WIN32_LEAN_AND_MEAN forces vcl0.h not to define WIN32_LEAN_AND_MEAN (note the missing NO_). WIN32_LEAN_AND_MEAN affects how many header files are pulled in when you include windows.h. If WIN32_LEAN_AND_MEAN is defined, fewer API header files are included (see windows.h to understand why). Defining NO_WIN32_LEAN_AND_MEAN prevents the definition of WIN32_LEAN_AND_MEAN, which in turn causes more API header files to be pulled in when windows.h is included (windows.h is included by all VCL apps via sysmac.h). These extra header files usually aren't necessary, and may increase your compile times slightly. Otherwise, the extra header files shouldn't cause any problems. HAVE A NICE DAY FOR YOU
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-06-27 01:01:26 IP:218.173.xxx.xxx 未訂閱

Add a file to the list of recently opened files

http://www.bcbdev.com/faqs/faq51.htm Answer: Windows 95 and Windows NT 4 allow users to re-open previous files by selecting the Documents menu option under the Start taskbar menu. For example, if you open a document in Microsoft Word, the filename is added to the recently opened documents list so you can access the file from the taskbar. To add a document to the list of recently opened files, use the SHAddToRecentDocs API function. Here is an example:
#include 
...
SHAddToRecentDocs(SHARD_PATH, "c:\\cbuilder\\readme.hlp");
Note: The first argument to SHAddToRecentDocs should be either SHARD_PATH or SHARD_PIDL. If you want to pass the filename as a string, use the SHARD_PATH value. SHARD_PIDL allows you to pass a pointer to an ITEMIDLIST (the ITEMIDLIST structure relates to shell programming with the shell namespace functions; SHGetDesktopFolder, SHGetMalloc and friends). Note: You can clear all of the items in the list of recent files by passing NULL as the second example. // Clear out all documents in the list SHAddToRecentDocs(SHARD_PATH, NULL); Note: While testing the code for this FAQ, I found out that the shell will not allow you to add a file to the recent files list if that file does not have an associated program. For example, I tried to add the file UNIT1.~H to the list. Since files with the ~H extension don't have a registered program that opens them, the shell refused to put UNIT1.~H in the list. This makes sense. When you select a file from the recent files list, Windows opens that file with its associated viewer. It can't open a file that has no associated viewer. This behavior was witnessed on Windows NT 4. Note: There is a a problem with shlobj.h and BCB 5. If you include shlobj.h in a BCB5 GUI project, you may get a strange compiler error, such as this: [C Error] shlobj.h(1762): E2238 Multiple declaration for 'FVSHOWINFO' [C Error] shlobj.h(1936): E2238 Multiple declaration for 'FOLDERSETTINGS' [C Error] shlobj.h(3717): E2238 Multiple declaration for 'DESKBANDINFO' [C Error] shlobj.h(4808): E2238 Multiple declaration for 'SHELLFLAGSTATE' You can eliminate these errors by adding the string NO_WIN32_LEAN_AND_MEAN to the conditional defines of your project. To see what impact this has, open the file vcl0.h in a text editor. HAVE A NICE DAY FOR YOU 發表人 - axsoft 於 2003/06/27 01:04:17
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-06-27 01:09:51 IP:218.173.xxx.xxx 未訂閱
Browse For Computer
Article 2
Keywords Browse, Shell
Download Source code and executable (193Kb)
Date July 10, 2001
Author Don Mastrovito
EMail don@dallastech.com
<!-- *** Begin content *** --> Various Windows applications, most notably Explorer, have the ability to browse the network for a computer. This is easily accomplished using the SHBrowseForFolder API.
SHBrowseForFolder is really misnamed. The API is capable of browsing for computers, directories, files, and printers. In this example, we'll only concentrate on computers. However, the code can easily be modified to search for the other objects. Input is in the form of a BROWSEINFO structure. Results are returned as named shell object. This browsing capability is dependent upon ComCtrls version 4.70 or later. That version was shipped with Internet Explorer 4. We will use Borland C Builder, but Microsoft Visual C could be used as well.
Create a new project (File|New|Application). Place a label, edit box, and a button on the default form. You should have something that looks like this:

Add #include to the main form source file. Shlobj.h contains the Windows Shell Object definitions. Like many Shell related defines and structs, Microsoft strips out what definitions they think are "unnecessary". That's the purpose of the WIN32_LEAN_AND_MEAN definition you'll find in several MS include files. Typically, Borland classes require those "extraneous" definitions, so we define the symbol NO_WIN32_LEAN_AND_MEAN. For convenience, we'll do it in the project defintion file (Demo.bpr). Go to Project|Options and select the Directories/Conditionals tab. Then look at the Conditional Defines section. Add NO_WIN32_LEAN_AND_MEAN to the list and press the OK button.
Add the following code to the button OnClick event to display the results of the call to SHBrowseForFolder:
    Answer->Text = BrowseForComputer("Pick one!");
Now add the following function that will perform all the work necessary to browse for a computer:
    AnsiString TForm1::BrowseForComputer(const AnsiString Title)
    {
    // Browse for computer dialog box
    // Call:
    //    Results = BrowseForComputer(Handle, prompt-text);            // Local storage
        BROWSEINFO      BrowseInfo;         // Browse API argument block
        PItemIDList     IDRoot;             // Shell object item ID for NetHood
        char            Path[MAX_PATH];     // Returned path (computer name)            // since TCommonDialog does not contain a window handle, grab
        // the handle of the currently active window in this thread
        HWND WindowHandle = GetActiveWindow();            // Get the Item ID for Network Neighborhood
        SHGetSpecialFolderLocation(WindowHandle, CSIDL_NETWORK, &IDRoot);            // Initialize
        memset(&BrowseInfo, '\0', sizeof(BROWSEINFO));
        memset(Path, '\0', sizeof(Path));
        BrowseInfo.hwndOwner = WindowHandle;
        BrowseInfo.pidlRoot = IDRoot;
        BrowseInfo.lpszTitle = Title.c_str();
        BrowseInfo.pszDisplayName = Path;
        BrowseInfo.ulFlags = BIF_BROWSEFORCOMPUTER;            // Show the browse dialog, get the Item ID for the selected item and
        // convert it to a path
        SHBrowseForFolder(&BrowseInfo); // or SHGetPathFromIDList(IDList, Path);            //Done
        return (AnsiString(Path));
    }
Compile and run the application. Pressing the Browse button invokes the SHBrowseForFolder API that causes the following dialog box to appear:

Upon successful completion, the API returns the computer name in as the display name string. That string is converted from a C-style string to an AnsiString and displayed in the edit box.
Download the source code and executable (193Kb).
<!-- *** End content *** -->
http://www.dallastech.com/BrowseForComputer/Index.html HAVE A NICE DAY FOR YOU 發表人 - axsoft 於 2003/06/27 08:42:44
bigdogchina
版主


發表:238
回覆:523
積分:312
註冊:2003-04-28

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-06-27 12:05:30 IP:211.162.xxx.xxx 未訂閱
谢谢大大们,按照您们的方法我已经解决问题了,现贴上我翻译的和实际编译了代码,肯定有不足之处,请大大们点拨一下我哦.
BROWSERINFO    函数功能: 得到用户选择的目录信息    typedef struct _browseinfo {        HWND          hwndOwner;
    LPCITEMIDLIST pidlRoot;
    LPCSTR        lpszTitle;
    UINT          ulFlags;
    BFFCALLBACK   lParam;
    int           iImage;
}  BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO;    参数:    hwndOwner
   对话框所属的窗体,可以设置为Application->Handle
pidlRoot
   一个指向ITEMIDLIST的指针,它详细的指出了浏览出现的根目录.如果为NULL,则以桌面文件夹为根目录
pszDisplayName
   选择后,所选目录的名称(不包含父级目录)被拷贝到这个指针指向的位置
lpszTitle
   作为标题显示在对话框中目录树的上面(最好设置为dlephi.ktop.com.tw吧)
ulFlags
   标志位,详细的说明了在对话框列表的类型,一般为:BIF_RETURNONLYFSDIRS 
这些参数包括零和下面更多的值:
   
   BIF_BROWSEFORCOMPUTER             仅仅返回选择的电脑.
   BIF_BROWSEFORPRINTER              仅仅返回选择的打印机.
   BIF_DONTGOBELOWDOMAIN             在网上邻居上显示的电脑,包括映射的文件夹等
   BIF_RETURNFSANCESTORS             如果用户选择了任何一个当前根目录,则"OK"变灰,只有选择当前目录下的子目录才行
   BIF_RETURNONLYFSDIRS                     只要是当前列出的目录,不管是否是根目录,都能使用 
   BIF_STATUSTEXT                    包含对话框的状态区域.这个回叫功能发送新的消息到对话框
lpfn
   回调函数,一般不用,设置为NULL
lParam
   预定义的对话框传递给回调函数的值
ilmage
   与所选目录相关联的图标在系统图标集合中的索引    
然后是编译通过了的代码(BCB5 Win2000 SP3)
//---------------------------------------------------------------------------
#define NO_WIN32_LEAN_AND_MEAN   //残念啊,一定要加在最前面
#include               //不得不包含啊    #include     #include     //是为了使用GlobalFreePtr()哦
#pragma hdrstop    #include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------    void __fastcall TForm1::Button1Click(TObject *Sender)
{
        //这是直接复制dllee大哥的代码
        String WorkDir;
        BROWSEINFO bi;
        char WDir[MAX_PATH];
        char FolderName[MAX_PATH];
        LPITEMIDLIST ItemID;            memset(&bi,0,sizeof(BROWSEINFO));
        memset(WDir,0,MAX_PATH);            bi.hwndOwner      = Handle;
        bi.pszDisplayName = FolderName;
        bi.lpszTitle      = "请选择需要的目录: ";
        ItemID = SHBrowseForFolder(&bi);
        SHGetPathFromIDList(ItemID,WDir);
        GlobalFreePtr(ItemID);
        WorkDir = String(WDir);
        ShowMessage(WorkDir);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
        //现在改一下哈
        char SelectDir[MAX_PATH];                   //最终用户选择的结果
        BROWSEINFO bi;                              //入参
        char FolderName[MAX_PATH];                  //所选择的目录名,例如选择了c:\winnt\system32,那就为system32
        LPITEMIDLIST ItemID;                        //所选目录的系统指针标志            memset(&bi,0,sizeof(BROWSEINFO));           //初始化入参的所有数据
        memset(SelectDir,0,MAX_PATH);               //初始化最终结果            bi.hwndOwner      = Application->Handle;
        bi.pszDisplayName = FolderName;
        bi.lpszTitle      = "Select Directory for dllee or axsoft: ";
        bi.ulFlags        = BIF_RETURNONLYFSDIRS;            ItemID = SHBrowseForFolder(&bi);           //打开目录对话框
        if(ItemID)
        {
            SHGetPathFromIDList(ItemID,SelectDir);  //获取所选目录的全名
            GlobalFreePtr(ItemID);                  //释放ItemID所占的资源
        }
        ShowMessage(SelectDir);
}
//---------------------------------------------------------------------------
同时真诚感谢dllee和axsoft两位大大的热心帮助!!! 人生在勤,不索何获?
------
人生在勤,不索何获?
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-06-27 16:21:19 IP:61.231.xxx.xxx 未訂閱
NO_WIN32_LEAN_AND_MEAN   是一定要 #define 而且要在最前面,這在 axsoft 版主提供的文件中已有說明,如果放在那,也可以放在 Project Option -> Directories/Conditionals 中的 Conditional defines 另外,我自己在試的時候是不需要 include shlobj.h 的,我的系統是 XP HomeEd SP1, BCB5 提供參考。    沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
bigdogchina
版主


發表:238
回覆:523
積分:312
註冊:2003-04-28

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-06-29 17:31:13 IP:211.162.xxx.xxx 未訂閱
dllee大大,建立一个目录窗体的问题是解决了,但是我总觉得还有点不完善哈! 比如在网际快车的目录对话框中就可以在其中直接建立目录,而且还可以有默认的下载路径,不知道它是怎么做的哦?我们是不是应该把注意力转移到BROWSERINFO的uflags这个BIF_STATUSTEXT参数上来?可是到这里我就傻眼了,还有可不可以用自己的窗体来代替 > 人生在勤,不索何获?
------
人生在勤,不索何获?
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-06-29 18:02:30 IP:61.224.xxx.xxx 未訂閱
如果是我自己寫的,只會很簡單的用 TOpenDialog,如下:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  OpenDialog1->InitialDir="."; // 自定初始目錄
  OpenDialog1->FileName="請選擇目錄";
  if(OpenDialog1->Execute())
  {
    ShowMessage(ExtractFilePath(OpenDialog1->FileName));
  }
}
如果真的要炫一點,我想,請您參考 turboted 版主的大作: ■【BCB】【發表】TreeView ListView 讀出系統檔案圖 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=30476 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
bigdogchina
版主


發表:238
回覆:523
積分:312
註冊:2003-04-28

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-07-01 22:17:42 IP:211.162.xxx.xxx 未訂閱
dllee大大,请您再回答我一个问题好吗? 我想调用"更改图标"对话框,该怎样做,指条明路嘛! 人生在勤,不索何获?
------
人生在勤,不索何获?
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-07-01 23:03:53 IP:61.224.xxx.xxx 未訂閱
引言: dllee大大,请您再回答我一个问题好吗? 我想调用"更改图标"对话框,该怎样做,指条明路嘛! 人生在勤,不索何获? < face="Verdana, Arial, Helvetica"> 請參考: http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20346308.html 或 http://www.codeproject.com/shell/selecticon.asp 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
bigdogchina
版主


發表:238
回覆:523
積分:312
註冊:2003-04-28

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-07-03 21:23:03 IP:211.162.xxx.xxx 未訂閱
感谢dllee大大,我的问题已经解决了 人生在勤,不索何获?
------
人生在勤,不索何获?
系統時間:2024-05-05 18:21:05
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!