Figure 1 VIRTOP.CPP
////////////////////////////////////////////////////////////////
// VIRTOP Copyright 1995 Microsoft Systems Journal.
// Simple program to demonstrate "virtual" operator<<.
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
//
// To compile, type
//
// cl virtop.cpp (Microsoft)
// bcc virtop.cpp (Borland)
// at the DOS prompt.
#include <iostream.h>
//////////////////
// Base class has friend operator and virtual protected print function.
//
class Fruit {
protected:
virtual void print(ostream& os) const = 0;
public:
friend ostream& operator<< (ostream& os, const Fruit& fruit);
};
//////////////////
// Derived classes implement their own print functions
//
class Apple : public Fruit {
protected:
virtual void print(ostream& os) const { os << "apple"; }
};
class Orange : public Fruit {
protected:
virtual void print(ostream& os) const { os << "orange"; }
};
////////////////
// There's just one operator<<
// It calls the virtual print function to do the work.
//
inline ostream& operator<< (ostream& os, const Fruit& fruit)
{
fruit.print(os);
return os;
}
////////////////
// Main program entry
//
int main()
{
Apple a;
Orange o;
Fruit* array[2] = { &a, &o };
// print the fruits using operator<<
for (int i=0; i<2; i++)
cout << "Fruit #" << i << " is a " << *array[i] << "\n";
return 0;
}
Figure 3 DCLIKBAR
DCLIKBAR.DEF
; dclikbar.def : Declares the module parameters for the application.
NAME DCLIKBAR
DESCRIPTION 'DCLIKBAR Windows Application'
EXETYPE WINDOWS
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE MULTIPLE
HEAPSIZE 1024 ; initial heap size
; Stack size is passed as argument to linker's /STACK option
DCLIKBAR.RC
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""res\\app.rc2"" // non-App Studio edited resources\r\n"
"\r\n"
"#include ""afxres.rc"" \011// Standard components\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
IDR_MAINFRAME ICON DISCARDABLE "RES\\APP.ICO"
IDR_DOCTYPE ICON DISCARDABLE "RES\\DOC.ICO"
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDR_MAINFRAME BITMAP MOVEABLE PURE "RES\\TOOLBAR.BMP"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MAINFRAME MENU PRELOAD DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New\tCtrl+N", ID_FILE_NEW
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&View"
BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
POPUP "&Help"
BEGIN
MENUITEM "&About DCLIKBAR...", ID_APP_ABOUT
END
END
IDR_DOCTYPE MENU PRELOAD DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New\tCtrl+N", ID_FILE_NEW
MENUITEM "&Close", ID_FILE_CLOSE
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&View"
BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
POPUP "&Window"
BEGIN
MENUITEM "&New Window", ID_WINDOW_NEW
MENUITEM "&Cascade", ID_WINDOW_CASCADE
MENUITEM "&Tile", ID_WINDOW_TILE_HORZ
MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE
END
POPUP "&Help"
BEGIN
MENUITEM "&About DCLIKBAR...", ID_APP_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE
BEGIN
"N", ID_FILE_NEW, VIRTKEY, CONTROL
"O", ID_FILE_OPEN, VIRTKEY, CONTROL
"S", ID_FILE_SAVE, VIRTKEY, CONTROL
"Z", ID_EDIT_UNDO, VIRTKEY, CONTROL
"X", ID_EDIT_CUT, VIRTKEY, CONTROL
"C", ID_EDIT_COPY, VIRTKEY, CONTROL
"V", ID_EDIT_PASTE, VIRTKEY, CONTROL
VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT
VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT
VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT
VK_F6, ID_NEXT_PANE, VIRTKEY
VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOG DISCARDABLE 34, 22, 165, 74
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About DCLIKBAR"
FONT 8, "MS Sans Serif"
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,11,10,18,20
LTEXT "DCLIKBAR Copyright 1995 Microsoft Systems Journal",
IDC_STATIC,45,10,93,18
LTEXT "Written by Paul DiLascia",IDC_STATIC,45,30,87,12
DEFPUSHBUTTON "OK",IDOK,45,49,32,14,WS_GROUP
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE PRELOAD DISCARDABLE
BEGIN
IDR_MAINFRAME "DCLIKBAR Windows Application"
IDR_DOCTYPE "\nDCLIKBAR\n\n\n\n\n"
END
STRINGTABLE PRELOAD DISCARDABLE
BEGIN
AFX_IDS_APP_TITLE "DCLIKBAR Windows Application"
AFX_IDS_IDLEMESSAGE "Ready"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_INDICATOR_EXT "EXT"
ID_INDICATOR_CAPS "CAP"
ID_INDICATOR_NUM "NUM"
ID_INDICATOR_SCRL "SCRL"
ID_INDICATOR_OVR "OVR"
ID_INDICATOR_REC "REC"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_FILE_NEW "Create a new document"
ID_FILE_OPEN "Open an existing document"
ID_FILE_CLOSE "Close the active document"
ID_FILE_SAVE "Save the active document"
ID_FILE_SAVE_AS "Save the active document with a new name"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_APP_ABOUT "Display program information, version number and
copyright"
ID_APP_EXIT "Quit the application; prompts to save documents"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_FILE_MRU_FILE1 "Open this document"
ID_FILE_MRU_FILE2 "Open this document"
ID_FILE_MRU_FILE3 "Open this document"
ID_FILE_MRU_FILE4 "Open this document"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_NEXT_PANE "Switch to the next window pane"
ID_PREV_PANE "Switch back to the previous window pane"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_WINDOW_NEW "Open another window for the active document"
ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window"
ID_WINDOW_CASCADE "Arrange windows so they overlap"
ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles"
ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles"
ID_WINDOW_SPLIT "Split the active window into panes"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_EDIT_CLEAR "Erase the selection"
ID_EDIT_CLEAR_ALL "Erase everything"
ID_EDIT_COPY "Copy the selection and put it on the Clipboard"
ID_EDIT_CUT "Cut the selection and put it on the Clipboard"
ID_EDIT_FIND "Find the specified text"
ID_EDIT_PASTE "Insert Clipboard contents"
ID_EDIT_REPEAT "Repeat the last action"
ID_EDIT_REPLACE "Replace specific text with different text"
ID_EDIT_SELECT_ALL "Select the entire document"
ID_EDIT_UNDO "Undo the last action"
ID_EDIT_REDO "Redo the previously undone action"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_VIEW_TOOLBAR "Show or hide the toolbar"
ID_VIEW_STATUS_BAR "Show or hide the status bar"
END
STRINGTABLE DISCARDABLE
BEGIN
AFX_IDS_SCSIZE "Change the window size"
AFX_IDS_SCMOVE "Change the window position"
AFX_IDS_SCMINIMIZE "Reduce the window to an icon"
AFX_IDS_SCMAXIMIZE "Enlarge the window to full size"
AFX_IDS_SCNEXTWINDOW "Switch to the next document window"
AFX_IDS_SCPREVWINDOW "Switch to the previous document window"
AFX_IDS_SCCLOSE "Close the active window and prompts to save the
documents"
END
STRINGTABLE DISCARDABLE
BEGIN
AFX_IDS_SCRESTORE "Restore the window to normal size"
AFX_IDS_SCTASKLIST "Activate Task List"
AFX_IDS_MDICHILD "Activate this window"
END
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "res\app.rc2" // non-App Studio edited resources
#include "afxres.rc" // Standard components
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
DCLIKBAR.H
////////////////////////////////////////////////////////////////
// DCLIKBAR Copyright 1995 Microsoft Systems Journal.
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
//
// See DCLIKBAR.CPP for Description of program.
#include "resource.h"
class CDclikbarApp : public CWinApp {
public:
CDclikbarApp();
virtual BOOL InitInstance();
//{{AFX_MSG(CDclikbarApp)
afx_msg void OnAppAbout();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
DCLIKBAR.CPP
////////////////////////////////////////////////////////////////
// DCLIKBAR Copyright 1995 Microsoft Systems Journal.
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// DCLIKBAR shows how to change the window class name of your application's
// main windows, and also how to implement a control bar that allows
// double-clicking.
//
// All the interesting code is in MAINFRM.CPP
// Makefiles: DCLIK152.MAK for VC++ 1.52
// DCLIKB22.MAK for VC++ 2.2
// DCLIKB40.MAK for VC++ 4.0
#include "stdafx.h"
#include "dclikbar.h"
#include "mainfrm.h"
#include "doc.h"
#include "view.h"
CDclikbarApp NEAR theApp;
BEGIN_MESSAGE_MAP(CDclikbarApp, CWinApp)
//{{AFX_MSG_MAP(CDclikbarApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
//}}AFX_MSG_MAP
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
END_MESSAGE_MAP()
CDclikbarApp::CDclikbarApp()
{
}
BOOL CDclikbarApp::InitInstance()
{
SetDialogBkColor(); // Set dialog background color to gray
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_DOCTYPE,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMyChildFrame),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
OnFileNew();
return TRUE;
}
class CAboutDlg : public CDialog {
public:
CAboutDlg() : CDialog(IDD_ABOUTBOX) { }
};
void CDclikbarApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
MAINFRM.H
//////////////////
// Derived toolbar class to handle double-clicks.
//
class CMyToolBar : public CToolBar {
static LPCSTR s_winClassName;
DECLARE_DYNAMIC(CMyToolBar)
protected:
#if _MFC_VER < 0x0400
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
#endif
//{{AFX_MSG(CMyToolBar)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//////////////////
// Standard main frame.
// Overrides PreCreateWindow to change window class name.
//
class CMainFrame : public CMDIFrameWnd {
static LPCSTR s_winClassName;
DECLARE_DYNAMIC(CMainFrame)
public:
CMainFrame();
virtual ~CMainFrame();
protected:
#if _MSC_VER < 0x0400
// Not required for MFC 4.0 and later.
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
#endif
CStatusBar m_wndStatusBar;
CMyToolBar m_wndToolBar;
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//////////////////
// Derived child frame overrides PreCreateWindow
// to change the window class name.
//
class CMyChildFrame : public CMDIChildWnd {
static LPCSTR s_winClassName;
DECLARE_DYNCREATE(CMyChildFrame)
public:
CMyChildFrame();
virtual ~CMyChildFrame();
protected:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
//{{AFX_MSG(CMyChildFrame)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
MAINFRM.CPP
#include "stdafx.h"
#include "dclikbar.h"
#include "mainfrm.h"
#ifndef AfxRegisterClass
// AfxRegisterClass is only defined in 32-bit versions of MFC
#define AfxRegisterClass ::RegisterClass
#endif
IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// Static class member holds window class name
// (NULL if not registered yet).
//
LPCSTR CMainFrame::s_winClassName = NULL;
static UINT BASED_CODE buttons[] = {
ID_FILE_NEW,
ID_SEPARATOR,
ID_APP_ABOUT
};
static UINT BASED_CODE indicators[] = {
ID_SEPARATOR,
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
CMainFrame::CMainFrame()
{
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.Create(this) ||
!m_wndToolBar.LoadBitmap(IDR_MAINFRAME) ||
!m_wndToolBar.SetButtons(buttons,
sizeof(buttons)/sizeof(UINT)) )
{
TRACE("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
}
return 0;
}
//////////////////
// Helper function to register a new window class based on an already
// existing window class, but with a different name and icon.
// Returns new name if successful; otherwise NULL.
//
static LPCSTR RegisterSimilarClass(LPCSTR lpszNewClassName,
LPCSTR lpszOldClassName, UINT nIDResource)
{
// Get class info for old class.
//
HINSTANCE hInst = AfxGetInstanceHandle();
WNDCLASS wc;
if (!::GetClassInfo(hInst, lpszOldClassName, &wc)) {
TRACE("Can't find window class %s\n", lpszOldClassName);
return NULL;
}
// Register new class with same info, but different name and icon.
//
wc.lpszClassName = lpszNewClassName;
wc.hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDResource));
if (!AfxRegisterClass(&wc)) {
TRACE("Unable to register window class%s\n", lpszNewClassName);
return NULL;
}
return lpszNewClassName;
}
//////////////////
// Override to register the different class and change window class name.
//
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CFrameWnd::PreCreateWindow(cs))
return FALSE;
if (s_winClassName==NULL) {
// One-time initialization: register the class
//
s_winClassName = RegisterSimilarClass("MyMainFrame",
cs.lpszClass, IDR_MAINFRAME);
if (!s_winClassName)
return FALSE;
}
cs.lpszClass = s_winClassName;
return TRUE;
}
////////////////////////////////////////////////////////////////
// CMyChildFrame implementation
//
IMPLEMENT_DYNCREATE(CMyChildFrame, CMDIChildWnd)
BEGIN_MESSAGE_MAP(CMyChildFrame, CMDIChildWnd)
//{{AFX_MSG_MAP(CMyChildFrame)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// Static class member holds window class name
// (NULL if not registered yet).
//
LPCSTR CMyChildFrame::s_winClassName = NULL;
CMyChildFrame::CMyChildFrame()
{
}
CMyChildFrame::~CMyChildFrame()
{
}
//////////////////
// Override to register the different class and change window class name.
//
BOOL CMyChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CMDIChildWnd::PreCreateWindow(cs))
return FALSE;
if (s_winClassName==NULL) {
// One-time initialization: register the class
//
s_winClassName = RegisterSimilarClass("MyChildFrame",
cs.lpszClass, IDR_DOCTYPE);
if (!s_winClassName)
return FALSE;
}
cs.lpszClass = s_winClassName;
return TRUE;
}
////////////////////////////////////////////////////////////////
// CMyToolBar implementation.
//
IMPLEMENT_DYNAMIC(CMyToolBar, CToolBar)
BEGIN_MESSAGE_MAP(CMyToolBar, CToolBar)
//{{AFX_MSG_MAP(CMyToolBar)
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//////////////////
// Handle double-click
//
void CMyToolBar::OnLButtonDblClk(UINT nFlags, CPoint point)
{
MessageBox("OK, I got the double-click. Now what?");
}
// Static class member holds window class name
// (NULL if not registered yet).
//
LPCSTR CMyToolBar::s_winClassName = NULL;
//////////////////
// Override this function to register the different class
// Required for pre-4.0 MFC ONLY! MFC version 4.0 and later uses
// real Win32 toolbar control, which accepts double-clicks,
// so there's no need to register a new class.
//
#if _MFC_VER < 0x0400
BOOL CMyToolBar::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CToolBar::PreCreateWindow(cs))
return FALSE;
if (s_winClassName==NULL) {
// One-time initialization: register new class with same info,
// but different name and style.
//
WNDCLASS wc;
HINSTANCE hInst = AfxGetInstanceHandle();
// Get data for AfxControlBar
if (!::GetClassInfo(hInst, cs.lpszClass, &wc)) {
TRACE("Can't find window class \"%s\"\n", cs.lpszClass);
return FALSE;
}
// Change name and style to allow double-clicks
wc.lpszClassName = "MyControlBar";
wc.style |= CS_DBLCLKS;
if (!AfxRegisterClass(&wc)) {
TRACE("Unable to register window class MyControlBar\n");
return FALSE;
}
s_winClassName = wc.lpszClassName;
}
cs.lpszClass = s_winClassName;
return TRUE;
}
#endif // _MFC_VER
Figure 6 Creating a Toolbar that Handles Double Clicks<
LPCSTR CMyToolBar::s_winClassName = NULL;
BOOL CMyToolBar::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CToolBar::PreCreateWindow(cs))
return FALSE;
if (s_winClassName==NULL) {
// One-time initialization: register new class
// with same info, but different name and style.
// Get data for AfxControlBar
WNDCLASS wc;
VERIFY(::GetClassInfo(AfxGetInstanceHandle(),
cs.lpszClass, &wc));
// Change name and style to allow double-clicks
wc.lpszClassName = "MyControlBar";
wc.style |= CS_DBLCLKS;
VERIFY(AfxRegisterClass(&wc));
s_winClassName = wc.lpszClassName;
}
cs.lpszClass = s_winClassName;
return TRUE;
}
Figure 8 New Write Function for TRACEWIN
// Modified Write function from TRACEWIN.H
//
void CMfxTrace::Write(const void* lpBuf, UINT nCount)
{
if (!afxTraceEnabled)
return;
CWnd *pTraceWnd = CWnd::FindWindow(TRACEWND_CLASSNAME, NULL);
if (pTraceWnd) {
// Found Trace window: send string with WM_COPYDATA
//
COPYDATASTRUCT cds;
cds.dwData = ID_COPYDATA_TRACEMSG;
cds.cbData = nCount;
cds.lpData = (void*)lpBuf;
pTraceWnd->SendMessage(WM_COPYDATA,
(WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),
(LPARAM)&cds);
} else {
// No trace window: do normal debug thing
//
::OutputDebugString((LPCSTR)lpBuf);
}
}
Figure 9 Modified MAINFRM.CPP from TRACEWIN
// (From modified TRACEWIN source, mainfrm.cpp)
//
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_MESSAGE(WM_COPYDATA, OnTraceMsg)
.
.
.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//////////////////
// Someone sent me a WM_COPYDATA message: display it.
//
LRESULT CMainFrame::OnTraceMsg(WPARAM wParam, LPARAM lParam)
{
COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
if (m_nOutputWhere==ID_OUTPUT_OFF || pcds->dwData!=ID_COPYDATA_TRACEMSG)
return 0;
const char* lpText = (const char*)pcds->lpData;
DWORD len = pcds->cbData;
if (m_nOutputWhere==ID_OUTPUT_TO_WINDOW) {
// Convert \n to \n\r for Windows brain-damaged edit control
// It's 1995, and I'm still writing code like this!
//
const char* src = lpText;
const char* endsrc = lpText + len;
char buf[1024];
char* dst = buf;
char* endbuf = buf + sizeof(buf) - 1;
while (src < endsrc && dst < endbuf) {
if (*src == '\n')
*dst++ = '\r';
*dst++ = *src++;
}
*dst = 0;
// Append string to contents of trace buffer
m_wndBuffer.SetSel(-1, -1); // end of edit text
m_wndBuffer.ReplaceSel(buf); // append string..
m_wndBuffer.SendMessage(EM_SCROLLCARET); // ..and show caret
} else if (m_nOutputWhere==ID_OUTPUT_TO_FILE) {
m_file.Write(lpText, len);
}
return 0;
}