////////////////////////////////////////////////////////////////
// EditCast 1997 Microsoft Systems Journal.
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// EditCast illustrates why it's not safe to cast the return from
// CWnd::GetDlgItem to a CEdit or other kind of window class.
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include "resource.h"
#include "TraceWin.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////
// Dialog class that alters the TAB sequence and handles
// the RETURN key.
//
class CMyDialog : public CDialog {
public:
CMyDialog();
~CMyDialog();
virtual BOOL OnInitDialog();
afx_msg void OnButton();
DECLARE_MESSAGE_MAP()
};
////////////////////////////////////////////////////////////////
// Application class
//
class CApp : public CWinApp {
public:
CApp() { }
virtual BOOL InitInstance();
} the App;
/////////////////
// Initialize: just run the dialog and quit.
//
BOOL CApp::InitInstance()
{
CMyDialog dlg;
dlg.DoModal();
return FALSE;
}
////////////////////////////////////////////////////////////////
// CMyDialog
//
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_BN_CLICKED(IDC_BUTTON1, OnButton)
END_MESSAGE_MAP()
//////////////////
// Construct dialog: set everything to zero or NULL.
//
CMyDialog::CMyDialog() : CDialog(IDD_DIALOG1)
{
}
CMyDialog::~CMyDialog()
{
}
/////////////////
// Initialize dialog: load accelerators and set initial focus.
//
BOOL CMyDialog::OnInitDialog()
{
return CDialog::OnInitDialog();
}
/////////////////
// Button handler: do demo stuff
//
void CMyDialog::OnButton()
{
// Get the window
CWnd* pWnd = GetDlgItem(IDC_EDIT1);
ASSERT(pWnd);
// Demonstrate that pWnd is not an edit control.
CEdit* pEdit = dynamic_cast<CEdit*>(pWnd);
BOOL bIsEdit = pWnd->IsKindOf(RUNTIME_CLASS(CEdit));
TRACE("GetDlgItem(IDC_EDIT1) returns CWnd = %p\n", pWnd);
TRACE("dynamic_cast to CEdit* = %p\n", pEdit);
TRACE("pWnd->IsKindOf(RUNTIME_CLASS(CEdit)) returns %d\n", bIsEdit);
// But you can treat it as one! (Do this at your own risk)
pEdit = (CEdit*)pWnd;
pEdit->SetSel(0, -1);
pEdit->ReplaceSel("");
pEdit->SetFocus();
}
Figure 3 StatLink
StatLink.h
//////////////////////////////////////////////////////////////////
// CStaticLink 1997 Microsoft Systems Journal.
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
////////////////
// CStaticLink implements a static control that's a hyperlink
// to any file on your desktop or web. You can use it in dialog boxes
// to create hyperlinks to web sites. When clicked, opens the file/URL
//
class CStaticLink : public CStatic {
public:
CStaticLink();
// you can change the Se any time:
COLORREF m_colorUnvisited; // color for unvisited
COLORREF m_colorVisited; // color for visited
BOOL m_bVisited; // whether visited or not
// URL/filename for non-text controls (e.g., icon, bitmap) or when link is
// different from window text. If you don't set this, CStaticIcon will
// use GetWindowText to get the link.
CString m_link;
protected:
DECLARE_DYNAMIC(CStaticLink)
CFont m_font; // underline font for text control
// message handlers
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
afx_msg void OnClicked();
DECLARE_MESSAGE_MAP()
};
StatLink.cpp
//////////////////////////////////////////////////////////////////
// CStaticLink 1997 Microsoft Systems Journal.
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// CStaticLink implements a static control that's a hyperlink
// to any file on your desktop or web. You can use it in dialog boxes
// to create hyperlinks to web sites. When clicked, opens the file/URL
//
#include "StdAfx.h"
#include "StatLink.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CStaticLink, CStatic)
BEGIN_MESSAGE_MAP(CStaticLink, CStatic)
ON_WM_CTLCOLOR_REFLECT()
ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
END_MESSAGE_MAP()
///////////////////
// Constructor sets default colors = blue/purple.
//
CStaticLink::CStaticLink()
{
m_colorUnvisited = RGB(0,0,255); // blue
m_colorVisited = RGB(128,0,128); // purple
m_bVisited = FALSE; // not visited yet
}
//////////////////// Handle reflected WM_CTLCOLOR to set custom control color.
// For a text control, use visited/unvisited colors and underline font.
// For non-text controls, do nothing. Also ensures SS_NOTIFY is on.
//
HBRUSH CStaticLink::CtlColor(CDC* pDC, UINT nCtlColor)
{
ASSERT(nCtlColor == CTLCOLOR_STATIC);
DWORD dwStyle = GetStyle();
if (!(dwStyle & SS_NOTIFY)) {
// Turn on notify flag to get mouse messages and STN_CLICKED.
// Otherwise, I'll never get any mouse clicks!
::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle | SS_NOTIFY);
}
HBRUSH hbr = NULL;
if ((dwStyle & 0xFF) <= SS_RIGHT) {
// this is a text control: set up font and colors
if (!(HFONT)m_font) {
// first time init: create font
LOGFONT lf;
GetFont()->GetObject(sizeof(lf), &lf);
lf.lfUnderline = TRUE;
m_font.CreateFontIndirect(&lf);
}
// use underline font and visited/unvisited colors
pDC->SelectObject(&m_font);
pDC->SetTextColor(m_bVisited ? m_colorVisited : m_colorUnvisited);
pDC->SetBkMode(TRANSPARENT);
// return hollow brush to preserve parent background color
hbr = (HBRUSH)::GetStockObject(HOLLOW_BRUSH);
}
return hbr;
}
/////////////////
// Handle mouse click: open URL/file.
//
void CStaticLink::OnClicked()
{
if (m_link.IsEmpty()) // if URL/filename not set..
GetWindowText(m_link); // ..get it from window text
// Call ShellExecute to run the file.
// For an URL, this means opening it in the browser.
//
HINSTANCE h = ShellExecute(NULL, "open", m_link, NULL, NULL, SW_SHOWNORMAL);
if ((UINT)h > 32) {
m_bVisited = TRUE; // (not really--might not have found link)
Invalidate(); // repaint to show visited color
} else {
MessageBeep(0); // unable to execute file!
TRACE(_T("*** WARNING: CStaticLink: unable to execute file %s\n"),
(LPCTSTR)m_link);
}
}
Figure 4 AboutDlg.cpp
////////////////////////////////////////////////////////////////
// ABOUTDLG 1997 Microsoft Systems Journal.
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// ABOUTDLG illustrates how to use CStaticLink to implement an About
// dialog with a web link in it.
#include "StdAfx.h"
#include "Resource.h"
#include "StatLink.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////
// Standard main frame class
class CMainFrame : public CFrameWnd {
protected:
DECLARE_DYNAMIC(CMainFrame)
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
/////////////////
// Standard app class
class CMyApp : public CWinApp {
public:
CMyApp();
protected:
DECLARE_DYNAMIC(CMyApp)
virtual BOOL InitInstance();
afx_msg void OnAppAbout();
DECLARE_MESSAGE_MAP()
};
////////////////////////////////////////////////////////////////
// CMyApp implementation
CMyApp the App;
IMPLEMENT_DYNAMIC(CMyApp, CWinApp)
BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
END_MESSAGE_MAP()
CMyApp::CMyApp()
{
}
//////////////////
// Standard InitInstance
BOOL CMyApp::InitInstance()
{
// Create main frame window (don't use doc/view stuff)
//
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
m_pMainWnd = pMainFrame;
return TRUE;
}
//////////////////
// Custom about dialog uses CStaticLink for hyperlinks.
// * for text control, URL is specified as text in dialog editor
// * for icon control, URL is specified by setting m_iconLink.m_link
class CAboutDlg : public CDialog {
public:
CAboutDlg() : CDialog(IDD_ABOUTBOX) { }
protected:
CStaticLink m_textLink; // static text
CStaticLink m_iconLink; // static icon
//////////////////
// Initialize dialog: subclass static controls
virtual BOOL OnInitDialog() {
m_textLink.SubclassDlgItem(IDC_URLTEXT, this);
m_iconLink.SubclassDlgItem(IDC_URLICON, this);
m_iconLink.m_link = _T("http://www.microsoft.com/msj");
return CDialog::OnInitDialog();
}
};
//////////////////
// Handle Help | About : run the About dialog
void CMyApp::OnAppAbout()
{
CAboutDlg().DoModal();
}
////////////////////////////////////////////////////////////////
// CMainFrame implementation
IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
static UINT BASED_CODE indicators[] = {
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.Create(this) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) {
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT))) {
TRACE("Failed to create status bar\n");
return -1; // fail to create
}
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
return 0;
}