请教关于浏览路径对话框该怎样创建,在<<如何调用浏览路径对话框 ShowMan(原作)>>中 BROWSEINFO bi; ITEMIDLIST*pidl是什么啊!!!

westerly 2002-01-17 12:19:00
...全文
88 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
蒋晟 2002-01-17
  • 打赏
  • 举报
回复
……
忘了……用用就知道了
westerly 2002-01-17
  • 打赏
  • 举报
回复
大哥看不懂啊能把思路说一下吗??
蒋晟 2002-01-17
  • 打赏
  • 举报
回复
怎么汉字贴出来成了乱码??:(
蒋晟 2002-01-17
  • 打赏
  • 举报
回复
//helper function of class BrowseForFolder
#define _ILSkip(pidl, cb) ((LPITEMIDLIST)(((BYTE*)(pidl))+cb))
#define _ILNext(pidl) _ILSkip(pidl, (pidl)->mkid.cb)
extern DECLARE_DLL_PUBLIC_API HRESULT FreeResources(LPVOID pData);
extern DECLARE_DLL_PUBLIC_API HRESULT TestPidl(LPITEMIDLIST pidl);
extern DECLARE_DLL_PUBLIC_API LPITEMIDLIST PidlFromVARIANT(VARIANT* pvarLoc);
extern DECLARE_DLL_PUBLIC_API LPSAFEARRAY MakeSafeArrayFromData(LPBYTE pData,DWORD cbData);
extern DECLARE_DLL_PUBLIC_API HRESULT InitVARIANTFromPidl(LPVARIANT pVar, LPITEMIDLIST pidl);
extern DECLARE_DLL_PUBLIC_API UINT ILGetSize(LPITEMIDLIST pidl);
extern DECLARE_DLL_PUBLIC_API LPITEMIDLIST GetNextItem(LPCITEMIDLIST pidl);
extern DECLARE_DLL_PUBLIC_API int CALLBACK TreeViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
extern DECLARE_DLL_PUBLIC_API LPITEMIDLIST CopyItemID(LPITEMIDLIST pidl);
extern DECLARE_DLL_PUBLIC_API BOOL GetName (LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, DWORD dwFlags, LPSTR lpFriendlyName);
extern DECLARE_DLL_PUBLIC_API void GetNormalAndSelectedIcons (LPITEMIDLIST lpifq, LPTV_ITEM lptvitem);
extern DECLARE_DLL_PUBLIC_API int GetIcon (LPITEMIDLIST lpi, UINT uFlags);
extern DECLARE_DLL_PUBLIC_API LPITEMIDLIST Concatenate(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
extern DECLARE_DLL_PUBLIC_API LPITEMIDLIST Copy(LPCITEMIDLIST pidlSource);
extern DECLARE_DLL_PUBLIC_API UINT GetSize(LPCITEMIDLIST pidl);
extern DECLARE_DLL_PUBLIC_API HRESULT ItemIdListFromPath( LPITEMIDLIST& pidl,LPCSTR szPath);

class DECLARE_DLL_PUBLIC_CLASS CBrowseForFolder
{
public:
CBrowseForFolder( HWND hParent = NULL, //parent window
LPITEMIDLIST pidl = NULL);//root dir
virtual ~CBrowseForFolder() ;
//Attributes
protected:
BROWSEINFO m_bi;
HWND m_hwnd;
LPITEMIDLIST m_pidlRoot;
char m_szDisplayName[MAX_PATH];
char m_szPathSelected[MAX_PATH];
CString m_strTitle;
UINT m_uFlags;
CString m_strPath;
BFFCALLBACK m_lpfn;
static int CALLBACK BrowseCallbackProc( HWND hwnd, UINT uMsg,
LPARAM lParam, LPARAM lpData);
public:
//browse flags,see SHBrowseForFolder
static const DWORD BROWSEFORCOMPUTER;
static const DWORD BROWSEFORPRINTER;
static const DWORD BROWSEINCLUDEFILES;
static const DWORD DONTGOBELOWDOMAIN;
static const DWORD EDITBOX;
static const DWORD RETURNFSANCESTORS;
static const DWORD RETURNONLYFSDIRS;
static const DWORD STATUSTEXT;
static const DWORD VALIDATE;
void SetOwner(HWND hwndOwner);
void SetRoot(LPITEMIDLIST pidl=NULL);
void SetRoot(LPCTSTR lpszRootPath=NULL);
CString GetTitle() ;
void SetTitle(LPCTSTR lpszTitle);
BOOL SetTitle(int nTitleID);
CString GetDisplayName();//if C: has label SYSTEM,the path c:\ is displayed SYSTEM(C:).
CString GetSelectedPath();
void SetFlags(UINT ulFlags);
UINT GetFlags() {return m_bi.ulFlags;};
void SetCallbackFunc(BFFCALLBACK lpfn=BrowseCallbackProc);//you can use your own hook functions.
int GetImage() { return m_bi.iImage;};//get icon index of selected item in system image list.

//Operations
public:
CTreeCtrl* m_pTree;
CEdit* m_pEdit;
BOOL Browse();//display the select folder dialog
protected:
virtual void OnInit() ;
virtual void OnSelChanged( LPITEMIDLIST pidl) ;
virtual void OnValidFailed() ;
void EnableOK(BOOL bEnable) ;
void SetSelection(LPITEMIDLIST pidl) ;
void SetSelection(LPCTSTR lpszPath) ;
void SetStatusText(LPCTSTR lpszText) ;
};
const DWORD CBrowseForFolder::BROWSEFORCOMPUTER=BIF_BROWSEFORCOMPUTER;
const DWORD CBrowseForFolder::BROWSEFORPRINTER=BIF_BROWSEFORPRINTER;
const DWORD CBrowseForFolder::BROWSEINCLUDEFILES=BIF_BROWSEINCLUDEFILES;
const DWORD CBrowseForFolder::DONTGOBELOWDOMAIN=BIF_DONTGOBELOWDOMAIN;
const DWORD CBrowseForFolder::EDITBOX=BIF_EDITBOX;
const DWORD CBrowseForFolder::RETURNFSANCESTORS=BIF_RETURNFSANCESTORS;
const DWORD CBrowseForFolder::RETURNONLYFSDIRS=BIF_RETURNONLYFSDIRS;
const DWORD CBrowseForFolder::STATUSTEXT=BIF_STATUSTEXT;
const DWORD CBrowseForFolder::VALIDATE=BIF_VALIDATE;

//////////////////////////////////////////////////////////////////////
//
// ruction/Destruction
//////////////////////////////////////////////////////////////////////

CBrowseForFolder::CBrowseForFolder( HWND hParent/*=NULL*/,
LPITEMIDLIST pidl/*=NULL*/)
{
m_hwnd = NULL;
SetOwner(hParent);
SetRoot(pidl);
m_lpfn=BrowseCallbackProc;
m_pidlRoot=pidl;
m_bi.ulFlags=EDITBOX |RETURNONLYFSDIRS|STATUSTEXT|BIF_VALIDATE;
}

CBrowseForFolder::~CBrowseForFolder()
{
}
//////////////////////////////////////////////////////////////////////
//
// Implementation
//

void CBrowseForFolder::SetOwner( HWND hwndOwner)
{
if (m_hwnd != NULL)
return;
m_bi.hwndOwner = hwndOwner;
}

void CBrowseForFolder::SetRoot( LPITEMIDLIST pidl)
{
if (m_hwnd != NULL)
return;
m_bi.pidlRoot = pidl;
}

void CBrowseForFolder::SetRoot(LPCTSTR lpszRootPath/*=NULL*/)
{
if(m_hwnd != NULL)
return;
if(lpszRootPath!=NULL){
if(FAILED(ItemIdListFromPath(m_pidlRoot,lpszRootPath))){
TRACE("Error Prasing path:%s.\n",lpszRootPath);
return;
}
m_bi.pidlRoot = m_pidlRoot;
}
else{
m_bi.pidlRoot = NULL;
}
}

CString CBrowseForFolder::GetTitle()
{return m_strTitle;}

void CBrowseForFolder::SetTitle( LPCTSTR lpszTitle)
{if (m_hwnd != NULL)return; m_strTitle=lpszTitle;}

BOOL CBrowseForFolder::SetTitle( int nTitleID)
{
if (nTitleID<= 0)return FALSE;
CString strTitle;
if(!strTitle.LoadString(nTitleID)) return FALSE;
SetTitle(strTitle);
return TRUE;
}

void CBrowseForFolder::SetFlags( UINT ulFlags)
{
if (m_hwnd != NULL) return;
m_bi.ulFlags = ulFlags;
}

CString CBrowseForFolder::GetDisplayName()
{
return m_szDisplayName;
}

CString CBrowseForFolder::GetSelectedPath()
{
return m_szPathSelected;
}

void CBrowseForFolder::SetCallbackFunc(BFFCALLBACK lpfn/*=BrowseCallbackProc*/)
{
m_lpfn=lpfn;
}

BOOL CBrowseForFolder::Browse()
{
BOOL bRet = FALSE;
m_bi.pszDisplayName = m_szDisplayName;
m_bi.lpszTitle = m_strTitle;
m_bi.lpfn=m_lpfn;
m_bi.lParam = (LPARAM)this;
LPITEMIDLIST pidl;
if ((pidl = ::SHBrowseForFolder(&m_bi)) != NULL){
m_strPath.Empty();
if (SUCCEEDED(::SHGetPathFromIDList(pidl, m_szPathSelected))){
bRet = TRUE;
m_strPath = m_szPathSelected;
}
LPMALLOC pMalloc;
//Retrieve a pointer to the shell's IMalloc interface
if (SUCCEEDED(SHGetMalloc(&pMalloc))){
pMalloc->Free(pidl);// free the PIDL that SHBrowseForFolder returned to us.
(void)pMalloc->Release();// release the shell's IMalloc interface
}
}
m_hwnd = NULL;
return bRet;
}

void CBrowseForFolder::OnInit()
{
CDialog dlg;
if(!dlg.Attach(m_hwnd)) return;
if(m_bi.ulFlags&EDITBOX){//initially,the editbox has not the same width the treectrl.Make it the same width.
m_pEdit=NULL;
m_pTree=NULL;
CWnd* pWndChild=dlg.GetWindow(GW_CHILD);
while(pWndChild!=NULL){//seek the editbox and the treectrl.
if(pWndChild->IsKindOf(RUNTIME_CLASS(CEdit)))
m_pEdit=(CEdit*)pWndChild;
if(pWndChild->IsKindOf(RUNTIME_CLASS(CTreeCtrl)))
m_pTree=(CTreeCtrl*)pWndChild;
pWndChild=pWndChild->GetWindow(GW_HWNDNEXT);
}
if(m_pEdit!=NULL&&m_pTree!=NULL){
CRect rcTree,reEdit;
m_pTree->GetWindowRect(&rcTree);
m_pEdit->GetWindowRect(&reEdit);
dlg.ScreenToClient(&rcTree);
dlg.ScreenToClient(&reEdit);
m_pEdit->MoveWindow(reEdit.left,reEdit.top,rcTree.Width(),reEdit.Height());
}
}
dlg.Detach();
}

void CBrowseForFolder::OnSelChanged( LPITEMIDLIST pidl)
{
char pszPath[MAX_PATH];
if(::SHGetPathFromIDList(pidl,pszPath)){//default action,set status text to current selection.
SetStatusText(pszPath);
}
}
void CBrowseForFolder::OnValidFailed()
{
::AfxMessageBox(IDS_INVALID_PATH,MB_TASKMODAL|MB_OK);//display a messagebox.you can provide your own validation messages.
}
void CBrowseForFolder::EnableOK( BOOL bEnable) //disable /enable the ok button
{
if (m_hwnd == NULL) return;
(void)SendMessage(m_hwnd, BFFM_ENABLEOK, (LPARAM)bEnable, NULL);
}

void CBrowseForFolder::SetSelection( LPITEMIDLIST pidl) //set current selection
{
if (m_hwnd == NULL) return;
(void)SendMessage(m_hwnd, BFFM_SETSELECTION, FALSE, (LPARAM)pidl);
}

void CBrowseForFolder::SetSelection( LPCTSTR lpszPath) //set current selection
{
if (m_hwnd == NULL) return;
(void)SendMessage(m_hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)lpszPath);
}

void CBrowseForFolder::SetStatusText( LPCTSTR lpszText) //set current status
{
if (m_hwnd == NULL) return;
(void)SendMessage(m_hwnd, BFFM_SETSTATUSTEXT, NULL, (LPARAM)lpszText);
}

int CALLBACK CBrowseForFolder::BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)//default hook function.
{
CBrowseForFolder* pbff = (CBrowseForFolder*)lpData;
pbff->m_hwnd = hwnd;
switch(uMsg){
case BFFM_INITIALIZED:
pbff->OnInit();
break;
case BFFM_SELCHANGED:
pbff->OnSelChanged((LPITEMIDLIST)lParam);
break;
case BFFM_VALIDATEFAILED :
pbff->OnValidFailed();
break;
}
return 0;//keep dialog displayed
}

// Exercise the PIDL by performing common operations upon it.
HRESULT TestPidl(LPITEMIDLIST pidl)//ͨ¹ýÖ´Ðг£ÓòÙ×÷²âÊÔPIDL
{
HRESULT hr;
LPSHELLFOLDER pshfDesktop = NULL, pshf = NULL;
DWORD uFlags = SHGDN_NORMAL;
STRRET strret;
if (!pidl){
return E_INVALIDARG;
}
hr = SHGetDesktopFolder(&pshfDesktop);
if (!pshfDesktop){
return hr;
}
//µÃµ½Óëpidl¶ÔÓ¦µÄpshf(ISHELLFODER¶ÔÏó)
hr = pshfDesktop->BindToObject(pidl,NULL,IID_IShellFolder,(LPVOID*)&pshf);
if (!pshf)
goto Error;
//µÃµ½Óëpidl¶ÔÓ¦µÄÏÔʾÃûstrret(·µ»Ø×Ö·û´®)
hr = pshfDesktop->GetDisplayNameOf(pidl, uFlags, &strret);
if (STRRET_WSTR == strret.uType)
FreeResources((LPVOID)strret.pOleStr);
Error:
if (pshf)
pshf->Release();
if (pshf)
pshfDesktop->Release();
return hr;
}

// Use the shell's IMalloc implementation to free resources
HRESULT FreeResources(LPVOID pData)//ʹÓÃÍâ¿ÇµÄImallocʵÏÖÊÍ·Å×ÊÔ´
{
HRESULT hr;
LPMALLOC pMalloc = NULL;

if (SUCCEEDED(hr = SHGetMalloc(&pMalloc)))
{
pMalloc->Free((LPVOID)pData);
pMalloc->Release();
}

return hr;
}

// Given a VARIANT, pull out the PIDL using brute force
LPITEMIDLIST PidlFromVARIANT(LPVARIANT pvarLoc)//´ÓVARIENT±äÁ¿Öеõ½PIDL
{
if (pvarLoc){
if (V_VT(pvarLoc) == (VT_ARRAY|VT_UI1)){
LPITEMIDLIST pidl = (LPITEMIDLIST)pvarLoc->parray->pvData;
return pidl;
}
}
return NULL;
}

// Pack a PIDL into a VARIANT
HRESULT InitVARIANTFromPidl(LPVARIANT pvar, LPITEMIDLIST pidl)//ÔÚVARIENT±äÁ¿Öдæ·ÅPIDL
{
if (!pidl || !pvar) {
return E_POINTER;
}
// Get the size of the pidl and allocate a SAFEARRAY of
// equivalent size
UINT cb = ILGetSize(pidl);
LPSAFEARRAY psa = MakeSafeArrayFromData((LPBYTE)pidl, cb);
if (!psa){
VariantInit(pvar);
return E_OUTOFMEMORY;
}
V_VT(pvar) = VT_ARRAY|VT_UI1;
V_ARRAY(pvar) = psa;
return NOERROR;
}

// Allocate a SAFEARRAY of cbData size and pack pData into it
LPSAFEARRAY MakeSafeArrayFromData(LPBYTE pData, DWORD cbData)//°²È«·ÖÅäcbData´óСµÄ°²È«Êý×飬²¢ÇÒ´æ·ÅpData¡£
{
LPSAFEARRAY psa;
if (!pData || 0 == cbData){
return NULL; // nothing to do
}
// create a one-dimensional safe array of BYTEs
psa = SafeArrayCreateVector(VT_UI1, 0, cbData);
if (psa){
// copy data into the area in safe array reserved for data
// Note we party directly on the pointer instead of using locking/
// unlocking functions. Since we just created this and no one
// else could possibly know about it or be using it, this is okay.
memcpy(psa->pvData,pData,cbData);
}
return psa;
}

// Get the size of the PIDL by walking the item id list
UINT ILGetSize(LPITEMIDLIST pidl)//ͨ¹ý±éÀúÏîÄ¿ÁбíµÃµ½PIDLµÄ´óС
{
UINT cbTotal = 0;
if (pidl){
cbTotal += sizeof(pidl->mkid.cb); // Null terminator
while (pidl->mkid.cb){
cbTotal += pidl->mkid.cb;
pidl = _ILNext(pidl);
}
}
return cbTotal;
}

HRESULT ItemIdListFromPath( LPITEMIDLIST& pidl,LPCSTR szPath)
//szPath is assumpted MAX_PATH size
{
LPSHELLFOLDER pDesktopFolder;
OLECHAR olePath[MAX_PATH];
ULONG chEaten;
ULONG dwAttributes;
HRESULT hr;
//
// Get a pointer to the Desktop's IShellFolder interface.
//
if (FAILED(SHGetDesktopFolder(&pDesktopFolder))){
return -1;
}
//
// IShellFolder::ParseDisplayName requires the file name be in
// Unicode.
//
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, olePath, MAX_PATH);
// Convert the path to an ITEMIDLIST.
hr = pDesktopFolder->ParseDisplayName(NULL,NULL,olePath,&chEaten,
&pidl,&dwAttributes);
if (FAILED(hr)){
// Handle error.
::AfxMessageBox (IDS_FAIL_PARSING_PATH);
}
// pidl now contains a pointer to an ITEMIDLIST for .\readme.txt.
// This ITEMIDLIST needs to be freed using the IMalloc allocator
// returned from SHGetMalloc().
//release the desktop folder object
pDesktopFolder->Release();
return 0;
}

LPITEMIDLIST GetNextItem(LPCITEMIDLIST pidl)
{
if(pidl)
return (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
else
return (NULL);
}
// CopyItemID - creates an item identifier list containing the first
// item identifier in the specified list.
// Returns a PIDL if successful, or NULL if out of memory.
LPITEMIDLIST CopyItemID(LPITEMIDLIST pidl)
{
// Get the size of the specified item identifier.
int cb = pidl->mkid.cb;
LPMALLOC pMalloc;
// Allocate a new item identifier list.
if(::SHGetMalloc (&pMalloc)!=S_OK)
return NULL;
LPITEMIDLIST pidlNew = (LPITEMIDLIST) pMalloc->Alloc(cb + sizeof(USHORT));
if (pidlNew == NULL)
return NULL;
// Copy the specified item identifier.
CopyMemory(pidlNew, pidl, cb);
// Append a terminating zero.
*((USHORT *) (((LPBYTE) pidlNew) + cb)) = 0;
pMalloc->Release ();
return pidlNew;
}

BOOL GetName (LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, DWORD dwFlags, LPSTR lpFriendlyName)
{
BOOL bSuccess = TRUE;
STRRET str;
if (NOERROR == lpsf->GetDisplayNameOf (lpi, dwFlags, &str)){
switch (str.uType){
case STRRET_WSTR:
WideCharToMultiByte ( CP_ACP, // code page
0 ,// dwFlags
str.pOleStr, // lpWideCharStr
-1, // cchWideChar
lpFriendlyName, // lpMultiByteStr
sizeof (lpFriendlyName), // cchMultiByte
NULL, // lpDefaultChar
NULL); // lpUsedDefaultChar
break;
case STRRET_OFFSET:
lstrcpy (lpFriendlyName, (LPSTR)lpi + str.uOffset);
break;
case STRRET_CSTR:
lstrcpy (lpFriendlyName, (LPSTR) str.cStr);
break;
default:
bSuccess = FALSE;
break;
}
}
else
bSuccess = FALSE;
return bSuccess;
}

void GetNormalAndSelectedIcons (LPITEMIDLIST lpifq, LPTV_ITEM lptvitem)
{
// Don't check the return value here.
// If GetIcon() fails, you're in big trouble.
lptvitem->iImage = GetIcon (lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

lptvitem->iSelectedImage = GetIcon (lpifq,
SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON);

return;
}

int GetIcon (LPITEMIDLIST lpi, UINT uFlags)
{
SHFILEINFO sfi;

SHGetFileInfo ((LPCSTR)lpi, 0, &sfi, sizeof (SHFILEINFO), uFlags);

return sfi.iIcon;
}

int CALLBACK TreeViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
{
LPSHELLFOLDER lpsf = (LPSHELLFOLDER)lpData;
if(!lpsf)
return 0;
return (int)lpsf->CompareIDs(0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2);
}
LPITEMIDLIST Concatenate(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
LPITEMIDLIST pidlNew;
UINT cb1 = 0,cb2 = 0;
//are both of these NULL?
if(!pidl1 && !pidl2)
return NULL;
//if pidl1 is NULL, just return a copy of pidl2
if(!pidl1)
{
pidlNew = Copy(pidl2);
return pidlNew;
}
//if pidl2 is NULL, just return a copy of pidl1
if(!pidl2)
{
pidlNew = Copy(pidl1);
return pidlNew;
}
cb1 = GetSize(pidl1) - sizeof(ITEMIDLIST);
cb2 = GetSize(pidl2);
//create the new PIDL
LPMALLOC pMalloc;
if(::SHGetMalloc (&pMalloc)!=S_OK)
return NULL;
pidlNew = (LPITEMIDLIST)pMalloc->Alloc(cb1 + cb2);
if(pidlNew)
{
//copy the first PIDL
CopyMemory(pidlNew, pidl1, cb1);
//copy the second PIDL
CopyMemory(((LPBYTE)pidlNew) + cb1, pidl2, cb2);
}
pMalloc->Release ();
return pidlNew;
}
LPITEMIDLIST Copy(LPCITEMIDLIST pidlSource)
{
LPITEMIDLIST pidlTarget = NULL;
UINT cbSource = 0;
if(NULL == pidlSource)
return (NULL);
LPMALLOC pMalloc;
if(::SHGetMalloc (&pMalloc)!=S_OK)
return NULL;
// Allocate the new pidl
cbSource = GetSize(pidlSource);
pidlTarget = (LPITEMIDLIST)pMalloc->Alloc(cbSource);
if(!pidlTarget)
return (NULL);
// Copy the source to the target
CopyMemory(pidlTarget, pidlSource, cbSource);
pMalloc->Release ();
return pidlTarget;
}
UINT GetSize(LPCITEMIDLIST pidl)
{
UINT cbTotal = 0;
LPITEMIDLIST pidlTemp = (LPITEMIDLIST) pidl;
if(pidlTemp)
{
while(pidlTemp->mkid.cb)
{
cbTotal += pidlTemp->mkid.cb;
pidlTemp = GetNextItem(pidlTemp);
}
//add the size of the NULL terminating ITEMIDLIST
cbTotal += sizeof(ITEMIDLIST);
}
return (cbTotal);
}
With the possible exceptions of boxer Muhammad Ali and baseball player Babe Ruth, no athlete has made a greater impact on American society-or in the world-than Michael Jordan. Follow the life of one of the most recognizable athletes and living brands inside this engaging and balanced biography. He is among the best-known and wealthiest athletes in the history of organized sports. With the possible exceptions of boxer Muhammad Ali and baseball player Babe Ruth, no athlete has made a greater impact on American society-or in the world-than Michael Jordan. Follow the life of one of the most recognizable athletes and living brands inside this engaging and balanced biography. When basketball stars Larry Bird and Magic Johnson retired in the early 1990s, Michael almost single-handedly propelled the NBA to stratospheric levels of success and international visibility. As a player for the Chicago Bulls, he generated instant crowd thrills with his record-setting drives and dunks, selling countless books, newspapers, videotapes, NBA game tickets, and hours of television time. The NBA promoted Michael, basing its popularity on his image as the greatest showman in sports history. Yet his sports hero status extends beyond NBA records. Michael changed the game by becoming the most effectively marketed athlete of his generation. Nike and many other companies rode-and continue to ride-on the coattails of Air Jordan's legend. Author David Porter highlights Jordan's on and off the court accomplishments and examines his relationship with Chicago Bulls' coaches, his commercial endorsements, and his current role as part-owner of the Charlotte Bobcats. A chronology, photos, career stats, and a bibliography of print and electronic resources round out this biography of one of the most influential athletes of the twentieth century.

1,650

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 非技术类
社区管理员
  • 非技术类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧