Re: TextOut() to a DialogBox ???
Peter Olcott wrote:
What are the options for directly writing text to a
DialogBox?
Peter, having a feel for what you want to do, in the simplest example,
1) You drop a static text control on your dialog box, the resource ID
would be (assuming its the first and you didn't change the id name)
IDC_STATIC
rename that to the appropiate name for your control, lets assume its
your response text:
IDC_STATIC_RESPONSE
2) Then when you want to set the text of the control, you can do
GetDlgItem(IDC_STATIC_RESPONSE)->SetWindowTextA(sResponseText);
where sResponseText is a the string you get from your service.
In your IDE, you can create a CStatic CONTROL for this resource ID. I
don't know which VS IDE you have, but you right click the control on
the form and you will see Add Variable option. It was so much easier
with the CLass Wizard in VS 6.0, but in my VS 2005 version, it will
allow you to create a CStatic Control or a VALUE in the Category pull
down.
If you change that to a VALUE, then it creates a CString member, give
it a name like:
m_response
now instead of directly going to the control window using
GetDlgItem(), you can simply do this:
m_response = sResponseText;
UpdateData(FALSE);
and it will display it for you.
Thats the skinny for this.
Now, assuming this is going to come from a request thread, in your
ProcessData() thread handler, you would do something like this:
void WINAPI ProcessData(TThreadData *data)
{
1) do work
2) generate a szResponseText (asciiz result string)
3) Send RESULT to MAIN THREAD GUI thread
}
Thats the TRICK in this typical design.
The GUI message pump is running on your main MFC process thread, there
are various methods to pass the data to the MAIN thread.
Some general methods are:
1) SendMessage or PostMesssage to a user defined message
::OnMyMessage() handler.
SendMessage is blocking so you don't want, posting
is what you want here.
2) You can set the result in a TThreadData fixed asciiz string
field and have a timer on the main thread that will display
the field, or send a signal to the main thread to display it.
3) Like 2, you use a synchronized global variable.
Now, I've done this so many times and in so many different ways, that
in general, when I being a project like this, what I do is instead of
dropping a static, I drop a LIST BOX for a log display.
Then in the control property editor, I disable the SORT by sending it
to false.
Then I use class wizard (under VS98) or Add Variable (under VS2005) to
create a control CListBox class with a field member name:
mc_log
(I use mc_ prefix for class control members, m_ for variables)
With that, now I can do this:
mc_log.AddString(sResponseText);
to append to the list box display any information I need to see from a
logging and even test debugging standpoint.
I have a simple CListbox subclass called CLogListBox with features for
adding a time stamp and optional append to a log file. I cleaned it
up to make it pure MFC.
------------------- CUT HERE: LogListBox.h ------------------
#pragma once
//-------------------------------------------------------
// LogListBox.h
// By Hector Santos, sant9442@gmail.com
// (c) copyright 2010 by Hector Santos
//
// Simple CLogListBox subclass for CListBox displaying
// with simple logging.
//
// Drop a Listbox to your dialog and Add Variable via
// class wizard using CLogListBox instead of CListBox
// for the member field name, i.e. mc_log.
//
// If you want a log file, in your InitDialog() add:
//
// mc_log.SetLogFile("c:\\mylogfie.log");
// mc_log.m_AddDate = true; // if you want dates
//
// Use the Log function to write log lines to the
// list box (and the log file if the file name set)
//
// mc_log.Log("Connecting to %s",m_Address);
//
// Use Log() just like a printf() function. No need
// to add "\n" to format string.
//-------------------------------------------------------
class CLogListBox : public CListBox
{
DECLARE_DYNAMIC(CLogListBox)
public:
CLogListBox();
virtual ~CLogListBox();
protected:
DECLARE_MESSAGE_MAP()
public:
// clear the log box
virtual void Clear(void);
// append to log box
virtual void Log(char * format, ...);
// set name of the log file
virtual void SetLogFile(const char * szLogFileName);
// Delete the log file
virtual BOOL DeleteLogFile(void);
// return time stamp
CString TimeStamp(const char *tag = NULL);
private:
// name of the log file
CString m_LogFileName;
// initially true, writes a header line the first time
bool m_firsttime;
public:
// set true to add a date with log time stamps
BOOL m_AddDate;
// date format use for logs, see CTime for formats
CString m_DateFmt;
// time format used for logs, see CTime for formats
CString m_TimeFmt;
// // Set TRUE for no time stamps in logs
BOOL m_NoTimeStamp;
};
------------------- CUT HERE: LogListBox.cpp ------------------
//-------------------------------------------------------
// LogListBox.cpp : implementation file
// By Hector Santos, sant9442@gmail.com
// (c) copyright 2010 by Hector Santos
//
// Simple CLogListBox subclass for CListBox displaying
// with simple logging.
//
// See LogListBox.h for usage information.
//-------------------------------------------------------
#include "stdafx.h"
#include "LogListBox.h"
// CLogListBox
IMPLEMENT_DYNAMIC(CLogListBox, CListBox)
CLogListBox::CLogListBox()
: m_AddDate(FALSE)
, m_LogFileName(_T(""))
, m_firsttime(TRUE)
, m_DateFmt(_T("%Y-%m-%d"))
, m_TimeFmt(_T("%H:%M:%S"))
, m_NoTimeStamp(FALSE)
{
// set default log name using the current process name
SetLogFile(NULL);
}
CLogListBox::~CLogListBox()
{
}
BEGIN_MESSAGE_MAP(CLogListBox, CListBox)
END_MESSAGE_MAP()
// CLogListBox message handlers
void CLogListBox::Clear(void)
{
ResetContent();
}
void CLogListBox::Log(char * format, ...)
{
va_list args;
va_start(args, format);
CString buf;
buf.FormatV(format, args);
va_end(args);
// append to list boix
CString sLine = "";
if (buf != "") sLine = TimeStamp(": ")+buf;
AddString(sLine);
// append to log file
if (m_LogFileName == "") return;
UINT flags = 0;
flags |= CFile::modeCreate | CFile::modeNoTruncate;
flags |= CFile::modeWrite | CFile::shareDenyNone | CFile::typeText;
CStdioFile fs;
if (fs.Open(m_LogFileName,flags)) {
fs.SeekToEnd();
if (m_firsttime) {
m_firsttime = false;
fs.WriteString(CString('-',78)+"\n");
}
fs.WriteString(sLine+"\n");
fs.Close();
}
}
CString CLogListBox::TimeStamp(const char *tag /* = NULL */)
{
if (m_NoTimeStamp) return "";
CTime ct = CTime::GetCurrentTime();
CString s = "";
if (m_AddDate) s = ct.Format(m_DateFmt)+" ";
s += ct.Format(m_TimeFmt);
if (tag && tag[0]) s += tag;
return s;
}
void CLogListBox::SetLogFile(const char * szLogFileName)
{
// if NULL, use process name for the log file name
if (szLogFileName == NULL) {
CHAR exefn[MAX_PATH*2] = {0};
if (GetModuleFileName(NULL,exefn,sizeof(exefn)-1)) {
CHAR *p = strrchr(exefn,'.');
if (p && !_strnicmp(p,".exe",4)) *p = 0;
m_LogFileName.Format("%s.log",exefn);
}
return;
}
m_LogFileName = szLogFileName;
}
BOOL CLogListBox::DeleteLogFile(void)
{
if (m_LogFileName != "") {
return DeleteFile(m_LogFileName);
}
return FALSE;
}
--
HLS