From: Hector Santos on
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(a)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(a)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
From: "Check Abdoul" checkabodul at mvps dot on
Subclass a CStatic control ( say CColorText ) and change its background and
foreground colors ( examples at codeguru.com or codeproject.com ). Add an
instance of this CColorText in your dialog and move it to the desired
location using SetWindowsPos() / MoveWindow() APIs.

----------
Cheers
Check Abdoul


"Peter Olcott" <NoSpam(a)OCR4Screen.com> wrote in message
news:e7qdnQgVv-FOrjTWnZ2dnUVZ_gmdnZ2d(a)giganews.com...
>
> "Peter Olcott" <NoSpam(a)OCR4Screen.com> wrote in message
> news:JpqdnVXVF9zAgTTWnZ2dnUVZ_iydnZ2d(a)giganews.com...
>> What are the options for directly writing text to a DialogBox?
>>
>
> Now I only need a way to convert this from clumsy Win32 to cleaner MFC:
>
> RECT rect;
> HDC hdc;
> PAINTSTRUCT ps;
> if (!(hdc = ::BeginPaint(this->m_hWnd, &ps) ) )
> ::MessageBox(this->m_hWnd, L"BeginPaint() failed", L"error", NULL);
> SetTextColor(hdc, RGB(0, 0, 0) );
> SetBkColor(hdc, RGB(245, 245, 245) );
> ::GetClientRect(this->m_hWnd, &rect);
> if (!TextOut(hdc, 45, 45, L"this is a test", 14) )
> ::MessageBox(this->m_hWnd, L"TextOut() failed", L"error", NULL);
> ::EndPaint(this->m_hWnd, &ps);
>
>


From: Liviu on
"Peter Olcott" <NoSpam(a)OCR4Screen.com> wrote in message
news:e7qdnQgVv-FOrjTWnZ2dnUVZ_gmdnZ2d(a)giganews.com...
>
> "Peter Olcott" <NoSpam(a)OCR4Screen.com> wrote in message
> news:JpqdnVXVF9zAgTTWnZ2dnUVZ_iydnZ2d(a)giganews.com...
>>
>> What are the options for directly writing text to a DialogBox?

Same as for TextOut'ing to any other window.
What have you tried, and how did it not work?

See also http://support.microsoft.com/kb/141863 for a few
different options - replace BitBlt with TextOut, of course.

> Now I only need a way to convert this from clumsy Win32
> to cleaner MFC:
>
> RECT rect;
> HDC hdc;
> PAINTSTRUCT ps;
> if (!(hdc = ::BeginPaint(this->m_hWnd, &ps) ) )
> ::MessageBox(this->m_hWnd, L"BeginPaint() failed", L"error", NULL);
> [...]

You must be half way there ;-) since "this->m_hWnd" is definitely
not Win32 API and looks very much like clumsy MFC already.

Btw, not directly relevant to your question, but using ::MessageBox
with L"" strings is inconsistent, and an error waiting to happen (next
time one changes the unicode settings). Either use ::MessageBoxW
with L"", or ""MessageBox with _T("").

Liviu



From: Peter Olcott on
All I was looking for is a conversion of this Win32 syntax
into MFC syntax.
This too is now moot. I don't use TextOut() to the
DialogBox, instead I paint my memory bitmap to the
DialogBox.

"Liviu" <lab2k1(a)gmail.c0m> wrote in message
news:eOjuMDvyKHA.5936(a)TK2MSFTNGP04.phx.gbl...
> "Peter Olcott" <NoSpam(a)OCR4Screen.com> wrote in message
> news:e7qdnQgVv-FOrjTWnZ2dnUVZ_gmdnZ2d(a)giganews.com...
>>
>> "Peter Olcott" <NoSpam(a)OCR4Screen.com> wrote in message
>> news:JpqdnVXVF9zAgTTWnZ2dnUVZ_iydnZ2d(a)giganews.com...
>>>
>>> What are the options for directly writing text to a
>>> DialogBox?
>
> Same as for TextOut'ing to any other window.
> What have you tried, and how did it not work?
>
> See also http://support.microsoft.com/kb/141863 for a few
> different options - replace BitBlt with TextOut, of
> course.
>
>> Now I only need a way to convert this from clumsy Win32
>> to cleaner MFC:
>>
>> RECT rect;
>> HDC hdc;
>> PAINTSTRUCT ps;
>> if (!(hdc = ::BeginPaint(this->m_hWnd, &ps) ) )
>> ::MessageBox(this->m_hWnd, L"BeginPaint() failed",
>> L"error", NULL);
>> [...]
>
> You must be half way there ;-) since "this->m_hWnd" is
> definitely
> not Win32 API and looks very much like clumsy MFC already.
>
> Btw, not directly relevant to your question, but using
> ::MessageBox
> with L"" strings is inconsistent, and an error waiting to
> happen (next
> time one changes the unicode settings). Either use
> ::MessageBoxW
> with L"", or ""MessageBox with _T("").
>
> Liviu
>
>
>


From: Liviu on
"Peter Olcott" <NoSpam(a)OCR4Screen.com> wrote in message
news:6JednUz8_oWf9jTWnZ2dnUVZ_s-dnZ2d(a)giganews.com...
> This too is now moot. I don't use TextOut() to the DialogBox,
> instead I paint my memory bitmap to the DialogBox.

Incidentally, the link I posted referred to bitmaps, but the techniques
also apply to TextOut or any other custom drawing/painting functions.

Liviu

P.S. Don't forget to unselect the bitmap from the DC when done ;-)

I had a longer reply at the time in the other thread, but it
happened to fall among those "dropped" by msnews' in recent days...

Anyway, in short, your wrong idea that "a CBitmap object has a default
value of a single black monchrome pixel" and the insistence that "Joe
said that today" denoted a complete misunderstanding of what Joe said,
and only confirmed the confusion on your part between GDI HBITMAP
handles vs. MFC CBitmap objects.