2013年9月

UuidFromString failed return code 0x000006a9

Let's check out the code below:

DEVNODE     dnSibling, dnChild;
CONFIGRET cr;
TCHAR GuidString[MAX_GUID_STRING_LEN];
ULONG ulSize = sizeof(GuidString);
GUID Guid;
INT iIndex;
BOOL bRet = FALSE;
RPC_STATUS rpcStatus;
cr = CM_Get_DevNode_Registry_Property_Ex(dn, CM_DRP_CLASSGUID, NULL, GuidString, &ulSize, 0, m_hMachine);
if (CR_SUCCESS != cr)
{
dnSibling = NULL;
break;
}
rpcStatus = UuidFromString((RPC_WSTR)&GuidString, &Guid);
bRet = SetupDiGetClassImageIndex(&m_ImageListData, &Guid, &iIndex);
if (bRet)
{
...
}

CM_Get_DevNode_Registry_Property_Ex function return a GUID style string GuidString like {4d36e97d-e325-11ce-bfc1-08002be10318}. and then I use UuidFromString to convert GUID style string to GUID data type. but rpcStatus return failed code:0x000006a9 . MSDN has explanation for this error code:

0x000006A9 RPC_S_INVALID_STRING_UUID The string UUID is invalid.

the problem is GUID shouldn't be like {4d36e97d-e325-11ce-bfc1-08002be10318} but 4d36e97d-e325-11ce-bfc1-08002be10318 which has no "{" and "}".

So, corrected code should be :

GuidString[MAX_GUID_STRING_LEN - 2] = _T('\0');
rpcStatus = UuidFromString((RPC_WSTR)&GuidString[1], &Guid);

MFC超链接扩展类:Chris Maunder的CHyperLink类

这个CHyperLink超链接类非常实用,完全能够满足我的需求。CHyperLink扩展自CStatic。直接贴出.h和.cpp文件。

这个文件应该是最新的版本,最后更新是200年2月29日。

这个CHyperLink类是加拿大人Chris Maunder所写。

此项目主页:http://www.codeproject.com/Articles/34/Hyperlink-control

P.S. CButtonST项目也是使用的这个类。

HyperLink.h

// HyperLink.h : header file
//
//
// HyperLink static control. Will open the default browser with the given URL
// when the user clicks on the link.
//
// Copyright Chris Maunder, 1997-1999 (cmaunder@mail.com)
// Feel free to use and distribute. May not be sold for profit.

// 2/29/00 -- P. Shaffer standard font mod.

#if !defined(AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

/////////////////////////////////////////////////////////////////////////////
// CHyperLink window

class CHyperLink : public CStatic
{
// Construction/destruction
public:
CHyperLink();
virtual ~CHyperLink();

public:
enum UnderLineOptions { ulHover = -1, ulNone = 0, ulAlways = 1};

// Attributes
public:
void SetURL(CString strURL);
CString GetURL() const;

void SetColours(COLORREF crLinkColour, COLORREF crVisitedColour,
COLORREF crHoverColour = -1);
COLORREF GetLinkColour() const;
COLORREF GetVisitedColour() const;
COLORREF GetHoverColour() const;

void SetVisited(BOOL bVisited = TRUE);
BOOL GetVisited() const;

void SetLinkCursor(HCURSOR hCursor);
HCURSOR GetLinkCursor() const;

void SetUnderline(int nUnderline = ulHover);
int GetUnderline() const;

void SetAutoSize(BOOL bAutoSize = TRUE);
BOOL GetAutoSize() const;

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CHyperLink)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL DestroyWindow();
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL

// Implementation
protected:
HINSTANCE GotoURL(LPCTSTR url, int showcmd);
void ReportError(int nError);
LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata);
void PositionWindow();
void SetDefaultCursor();

// Protected attributes
protected:
COLORREF m_crLinkColour, m_crVisitedColour; // Hyperlink colours
COLORREF m_crHoverColour; // Hover colour
BOOL m_bOverControl; // cursor over control?
BOOL m_bVisited; // Has it been visited?
int m_nUnderline; // underline hyperlink?
BOOL m_bAdjustToFit; // Adjust window size to fit text?
CString m_strURL; // hyperlink URL
CFont m_UnderlineFont; // Font for underline display
CFont m_StdFont; // Standard font
HCURSOR m_hLinkCursor; // Cursor for hyperlink
CToolTipCtrl m_ToolTip; // The tooltip
UINT m_nTimerID;

// Generated message map functions
protected:
//{{AFX_MSG(CHyperLink)
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//}}AFX_MSG
afx_msg void OnClicked();
DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_HYPERLINK_H__D1625061_574B_11D1_ABBA_00A0243D1382__INCLUDED_)

HyperLink.cpp

// HyperLink.cpp : implementation file
//
// HyperLink static control. Will open the default browser with the given URL
// when the user clicks on the link.
//
// Copyright (C) 1997 - 1999 Chris Maunder
// All rights reserved. May not be sold for profit.
//
// Thanks to P錶 K. T鴑der for auto-size and window caption changes.
//
// "GotoURL" function by Stuart Patterson
// As seen in the August, 1997 Windows Developer's Journal.
// Copyright 1997 by Miller Freeman, Inc. All rights reserved.
// Modified by Chris Maunder to use TCHARs instead of chars.
//
// "Default hand cursor" from Paul DiLascia's Jan 1998 MSJ article.
//
// 2/29/00 -- P. Shaffer standard font mod.

#include "stdafx.h"
#include "HyperLink.h"

#include "atlconv.h" // for Unicode conversion - requires #include <afxdisp.h> // MFC OLE automation classes

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define TOOLTIP_ID 1

/////////////////////////////////////////////////////////////////////////////
// CHyperLink

CHyperLink::CHyperLink()
{
m_hLinkCursor = NULL; // No cursor as yet
m_crLinkColour = RGB( 0, 0, 238); // Blue
m_crVisitedColour = RGB( 85, 26, 139); // Purple
m_crHoverColour = RGB(255, 0, 0); // Red
m_bOverControl = FALSE; // Cursor not yet over control
m_bVisited = FALSE; // Hasn't been visited yet.
m_nUnderline = ulHover; // Underline the link?
m_bAdjustToFit = TRUE; // Resize the window to fit the text?
m_strURL.Empty();
m_nTimerID = 100;
}

CHyperLink::~CHyperLink()
{
m_UnderlineFont.DeleteObject();
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink overrides

BOOL CHyperLink::DestroyWindow()
{
KillTimer(m_nTimerID);

return CStatic::DestroyWindow();
}

BOOL CHyperLink::PreTranslateMessage(MSG* pMsg)
{
m_ToolTip.RelayEvent(pMsg);
return CStatic::PreTranslateMessage(pMsg);
}


void CHyperLink::PreSubclassWindow()
{
// We want to get mouse clicks via STN_CLICKED
DWORD dwStyle = GetStyle();
::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);

// Set the URL as the window text
if (m_strURL.IsEmpty())
GetWindowText(m_strURL);

// Check that the window text isn't empty. If it is, set it as the URL.
CString strWndText;
GetWindowText(strWndText);
if (strWndText.IsEmpty())
{
ASSERT(!m_strURL.IsEmpty()); // Window and URL both NULL. DUH!
SetWindowText(m_strURL);
}

CFont* pFont = GetFont();
if (!pFont)
{
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
if (hFont == NULL)
hFont = (HFONT) GetStockObject(ANSI_VAR_FONT);
if (hFont)
pFont = CFont::FromHandle(hFont);
}
ASSERT(pFont->GetSafeHandle());

// Create the underline font
LOGFONT lf;
pFont->GetLogFont(&lf);
m_StdFont.CreateFontIndirect(&lf);
lf.lfUnderline = (BYTE) TRUE;
m_UnderlineFont.CreateFontIndirect(&lf);

PositionWindow(); // Adjust size of window to fit URL if necessary
SetDefaultCursor(); // Try and load up a "hand" cursor
SetUnderline();

// Create the tooltip
CRect rect;
GetClientRect(rect);
m_ToolTip.Create(this);
m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);

CStatic::PreSubclassWindow();
}

BEGIN_MESSAGE_MAP(CHyperLink, CStatic)
//{{AFX_MSG_MAP(CHyperLink)
ON_WM_CTLCOLOR_REFLECT()
ON_WM_SETCURSOR()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHyperLink message handlers

void CHyperLink::OnClicked()
{
m_bOverControl = FALSE;
int result = (int)GotoURL(m_strURL, SW_SHOW);
m_bVisited = (result > HINSTANCE_ERROR);
if (!m_bVisited)
{
MessageBeep(MB_ICONEXCLAMATION); // Unable to follow link
ReportError(result);
}
else
SetVisited(); // Repaint to show visited colour
}

HBRUSH CHyperLink::CtlColor(CDC* pDC, UINT nCtlColor)
{
ASSERT(nCtlColor == CTLCOLOR_STATIC);

if (m_bOverControl)
pDC->SetTextColor(m_crHoverColour);
else if (m_bVisited)
pDC->SetTextColor(m_crVisitedColour);
else
pDC->SetTextColor(m_crLinkColour);

// transparent text.
pDC->SetBkMode(TRANSPARENT);
return (HBRUSH)GetStockObject(NULL_BRUSH);
}

void CHyperLink::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bOverControl) // Cursor has just moved over control
{
m_bOverControl = TRUE;

if (m_nUnderline == ulHover)
SetFont(&m_UnderlineFont);
Invalidate();

SetTimer(m_nTimerID, 100, NULL);
}
CStatic::OnMouseMove(nFlags, point);
}

void CHyperLink::OnTimer(UINT nIDEvent)
{
CPoint p(GetMessagePos());
ScreenToClient(&p);

CRect rect;
GetClientRect(rect);
if (!rect.PtInRect(p))
{
m_bOverControl = FALSE;
KillTimer(m_nTimerID);

if (m_nUnderline != ulAlways)
SetFont(&m_StdFont);
rect.bottom+=10;
InvalidateRect(rect);
}

CStatic::OnTimer(nIDEvent);
}

BOOL CHyperLink::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/)
{
if (m_hLinkCursor)
{
::SetCursor(m_hLinkCursor);
return TRUE;
}
return FALSE;
}

BOOL CHyperLink::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(rect);
pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE));

return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink operations

void CHyperLink::SetURL(CString strURL)
{
m_strURL = strURL;

if (::IsWindow(GetSafeHwnd())) {
PositionWindow();
m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);
}
}

CString CHyperLink::GetURL() const
{
return m_strURL;
}

void CHyperLink::SetColours(COLORREF crLinkColour, COLORREF crVisitedColour,
COLORREF crHoverColour /* = -1 */)
{
m_crLinkColour = crLinkColour;
m_crVisitedColour = crVisitedColour;

if (crHoverColour == -1)
m_crHoverColour = ::GetSysColor(COLOR_HIGHLIGHT);
else
m_crHoverColour = crHoverColour;

if (::IsWindow(m_hWnd))
Invalidate();
}

COLORREF CHyperLink::GetLinkColour() const
{
return m_crLinkColour;
}

COLORREF CHyperLink::GetVisitedColour() const
{
return m_crVisitedColour;
}

COLORREF CHyperLink::GetHoverColour() const
{
return m_crHoverColour;
}

void CHyperLink::SetVisited(BOOL bVisited /* = TRUE */)
{
m_bVisited = bVisited;

if (::IsWindow(GetSafeHwnd()))
Invalidate();
}

BOOL CHyperLink::GetVisited() const
{
return m_bVisited;
}

void CHyperLink::SetLinkCursor(HCURSOR hCursor)
{
m_hLinkCursor = hCursor;
if (m_hLinkCursor == NULL)
SetDefaultCursor();
}

HCURSOR CHyperLink::GetLinkCursor() const
{
return m_hLinkCursor;
}

void CHyperLink::SetUnderline(int nUnderline /*=ulHover*/)
{
if (m_nUnderline == nUnderline)
return;

if (::IsWindow(GetSafeHwnd()))
{
if (nUnderline == ulAlways)
SetFont(&m_UnderlineFont);
else
SetFont(&m_StdFont);

Invalidate();
}

m_nUnderline = nUnderline;
}

int CHyperLink::GetUnderline() const
{
return m_nUnderline;
}

void CHyperLink::SetAutoSize(BOOL bAutoSize /* = TRUE */)
{
m_bAdjustToFit = bAutoSize;

if (::IsWindow(GetSafeHwnd()))
PositionWindow();
}

BOOL CHyperLink::GetAutoSize() const
{
return m_bAdjustToFit;
}


// Move and resize the window so that the window is the same size
// as the hyperlink text. This stops the hyperlink cursor being active
// when it is not directly over the text. If the text is left justified
// then the window is merely shrunk, but if it is centred or right
// justified then the window will have to be moved as well.
//
// Suggested by P錶 K. T鴑der

void CHyperLink::PositionWindow()
{
if (!::IsWindow(GetSafeHwnd()) || !m_bAdjustToFit)
return;

// Get the current window position
CRect WndRect, ClientRect;
GetWindowRect(WndRect);
GetClientRect(ClientRect);

ClientToScreen(ClientRect);

CWnd* pParent = GetParent();
if (pParent)
{
pParent->ScreenToClient(WndRect);
pParent->ScreenToClient(ClientRect);
}

// Get the size of the window text
CString strWndText;
GetWindowText(strWndText);

CDC* pDC = GetDC();
CFont* pOldFont = pDC->SelectObject(&m_UnderlineFont);
CSize Extent = pDC->GetTextExtent(strWndText);
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);

// Adjust for window borders
Extent.cx += WndRect.Width() - ClientRect.Width();
Extent.cy += WndRect.Height() - ClientRect.Height();

// Get the text justification via the window style
DWORD dwStyle = GetStyle();

// Recalc the window size and position based on the text justification
if (dwStyle & SS_CENTERIMAGE)
WndRect.DeflateRect(0, (WndRect.Height() - Extent.cy)/2);
else
WndRect.bottom = WndRect.top + Extent.cy;

if (dwStyle & SS_CENTER)
WndRect.DeflateRect((WndRect.Width() - Extent.cx)/2, 0);
else if (dwStyle & SS_RIGHT)
WndRect.left = WndRect.right - Extent.cx;
else // SS_LEFT = 0, so we can't test for it explicitly
WndRect.right = WndRect.left + Extent.cx;

// Move the window
SetWindowPos(NULL, WndRect.left, WndRect.top, WndRect.Width(), WndRect.Height(), SWP_NOZORDER);
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink implementation

// The following appeared in Paul DiLascia's Jan 1998 MSJ articles.
// It loads a "hand" cursor from the winhlp32.exe module
void CHyperLink::SetDefaultCursor()
{
if (m_hLinkCursor == NULL) // No cursor handle - load our own
{
// Get the windows directory
CString strWndDir;
GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
strWndDir.ReleaseBuffer();

strWndDir += _T("\\winhlp32.exe");
// This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
HMODULE hModule = LoadLibrary(strWndDir);
if (hModule) {
HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
if (hHandCursor)
m_hLinkCursor = CopyCursor(hHandCursor);
}
FreeLibrary(hModule);
}
}

LONG CHyperLink::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
{
HKEY hkey;
LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);

if (retval == ERROR_SUCCESS) {
long datasize = MAX_PATH;
TCHAR data[MAX_PATH];
RegQueryValue(hkey, NULL, data, &datasize);
lstrcpy(retdata,data);
RegCloseKey(hkey);
}

return retval;
}

void CHyperLink::ReportError(int nError)
{
CString str;
switch (nError) {
case 0: str = "The operating system is out\nof memory or resources."; break;
case SE_ERR_PNF: str = "The specified path was not found."; break;
case SE_ERR_FNF: str = "The specified file was not found."; break;
case ERROR_BAD_FORMAT: str = "The .EXE file is invalid\n(non-Win32 .EXE or error in .EXE image)."; break;
case SE_ERR_ACCESSDENIED: str = "The operating system denied\naccess to the specified file."; break;
case SE_ERR_ASSOCINCOMPLETE: str = "The filename association is\nincomplete or invalid."; break;
case SE_ERR_DDEBUSY: str = "The DDE transaction could not\nbe completed because other DDE transactions\nwere being processed."; break;
case SE_ERR_DDEFAIL: str = "The DDE transaction failed."; break;
case SE_ERR_DDETIMEOUT: str = "The DDE transaction could not\nbe completed because the request timed out."; break;
case SE_ERR_DLLNOTFOUND: str = "The specified dynamic-link library was not found."; break;
case SE_ERR_NOASSOC: str = "There is no application associated\nwith the given filename extension."; break;
case SE_ERR_OOM: str = "There was not enough memory to complete the operation."; break;
case SE_ERR_SHARE: str = "A sharing violation occurred. ";
default: str.Format(_T("Unknown Error (%d) occurred."), nError); break;
}
str = "Unable to open hyperlink:\n\n" + str;
AfxMessageBox(str, MB_ICONEXCLAMATION | MB_OK);
}

HINSTANCE CHyperLink::GotoURL(LPCTSTR url, int showcmd)
{
TCHAR key[MAX_PATH + MAX_PATH];

// First try ShellExecute()
HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);

// If it failed, get the .htm regkey and lookup the program
if ((UINT)result <= HINSTANCE_ERROR) {

if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS) {
lstrcat(key, _T("\\shell\\open\\command"));

if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) {
TCHAR *pos;
pos = _tcsstr(key, _T("\"%1\""));
if (pos == NULL) { // No quotes found
pos = _tcsstr(key, _T("%1")); // Check for %1, without quotes
if (pos == NULL) // No parameter at all...
pos = key+lstrlen(key)-1;
else
*pos = '\0'; // Remove the parameter
}
else
*pos = '\0'; // Remove the parameter

lstrcat(pos, _T(" "));
lstrcat(pos, url);

USES_CONVERSION;
result = (HINSTANCE) WinExec(T2A(key),showcmd);
}
}
}

return result;
}

Error -6118: The Resource compiler failed to build the specified RES file required to link the DLL.

用InstallShield创建了一个InstallScript项目,代码完成后编译报错:

Error -6118: The Resource compiler failed to build the specified RES file required to link the DLL.

Error -6118: The Resource compiler failed to build the specified RES file required to link the DLL.

点击错误码-6118进入Acresso官网知识库,是一个以-6118为关键字的搜索页面。点击看了几篇KB。说是可能是对话框资源(文字)有两点(..)造成的。还有可能是对话框上面的图片损坏造成。不过我这里的情况是找不到一个ico位图。

进入Dialogs,我编辑了对话框SdAskDestPath2 这个对话框有一个文件夹图标,名字叫IconId_10006.ico。到InstallShield安装目录找到这个图片,然后放到项目目录即可编译通过。

MFC中stdafx中afx前缀是什么意思有什么含义?

afx表示Application Framework eXtensions, 在Wikipedia页面中Application Framework eXtensions显示的标题却是Microsoft Foundation Class Library,说明他们是同一个东西。

以下来自维基百科的内容写道:

One interesting quirk of MFC is the use of "Afx" as the prefix for many functions, macros and the standard precompiled header name "stdafx.h". During early development what became MFC was called "Application Framework Extensions" and abbreviated "Afx". The name Microsoft Foundation Classes (MFC) was adopted too late in the release cycle to change these references.

MFC一个奇怪的地方是在大量函数、宏、预定义头文件中使用“AFX”前缀。这是因为在MFC的早期开发中,MFC的名字叫“Application Framework Extensions”(程序框架扩展),缩写是“Afx”。在MFC的后期发行周期中将Afx前缀修改掉已经是“不可挽回”了。这就是“Afx”的由来。

The old Stingray MFC FAQ中写道 :

In the beginning, Microsoft created a group called the AFX group (stands for (A)pplication (F)ramework(X)).

起初微软建立了一个 AFX小组。

[...]

The AFX group was actually responsible for two things: the MFC library and the IDE's support for MFC (namely, the resource editor and the wizards). The AFX name was dropped in April 1994, and the group's members simply became part of smaller teams within the Visual C++ group. One of those smaller teams is today's MFC team.

AFX小组负责两个事情:MFC库和IDE对MFC的支持(也就是Resource Editor、App Wizard、Class Wizard等)。1994年后弃用AFX这个名字。AFX小组成为了Visual C++小组的下属部门。这个下属部门组成了部分的MFC团队。

更多资料参考:

http://en.wikipedia.org/wiki/Stdafx.h