From: Hector Santos on 23 Mar 2010 19:38 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 23 Mar 2010 20:49 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 23 Mar 2010 21:22 "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 23 Mar 2010 21:29 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 23 Mar 2010 22:06
"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. |