|
http://dslweb.nwnexus.com/~ast/dload/guicon.htm
I've tried the code in the above link and it does work in redirecting stdout and stderr (even cin, cout, cerr work). Not sure how to use it with your class though.
The only documentation from microsoft about this that I found is in the following link:
http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q105/3/05.asp&NoWebContent=1
|
|
|
|
|
omasoud wrote:
http://dslweb.nwnexus.com/~ast/dload/guicon.htm
I've tried the code in the above link and it does work in redirecting stdout and stderr (even cin, cout, cerr work). Not sure how to use it with your class though.
Well, this code actually does only part of it. It shows how to attach an Win32 file HANDLE (in this case a console handle) to CRT output (stdout, stderr, cout, cerr) at runtime.
The other things to do are:
- create an anonymous pipe with CreatePipe and use its write end HANDLE (and not a console handle) as STDOUT and STDERR as shown in the example code you found.
- create a worker thread that reads from the pipe's read end HANDLE and dumps the output to the CEditLog.
Because CEditLog has been designed to be thread-safe, this all should not be too difficult. You just have to take care (a bit) about when creating the thread, CEditLog and how to shut all of them down in a correct and graceful order.
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
First thanks for the great class! I have used it and it works great
What I wan't to do is add coloring capability to it, that dpending on the text I can change its color.
Any pointers, suggestions as I think that would be a goot addition
Thanks again
|
|
|
|
|
annum wrote:
What I wan't to do is add coloring capability to it, that dpending on the text I can change its color.
This should be possible by building CEditLog around a RichEdit control instead of an ordinary edit control. (As a side effect this would also remove the 64kb limit on Win9x - however, I never really cared about this )
Since RichEdit understoods most (all) of the messages of an edit control, the task should not be that difficult. The point that let me intentionally avoid RichEdit in the days I wrote this code, was the versioning chaos around it (it seemed to depend on Windows /IE / common-control and whatever versions...).
Have fun!
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
When I tried to link up CEditLog to a RichEditCtrl. It crashed after a few seconds of scrolling. The callstack was pretty messed up, but I think it had to do with a windows message proc.
-p
|
|
|
|
|
Hi,
I was wondering if anyone has tried to use CEditLog on an Cedit control in a FormView ... I just set everything up and the program runs... no compile errors... the program does not crash... BUT when I send text to the CEditLog nothing happens???
Anyone have any idea what I am doing wrong, or why CEditLog would not work on a Cedit control in Formview?
Thanks for your help.
Abstract3
|
|
|
|
|
I have to admit that I never used a CFormView, but I just do not believe that it would not work. An edit control is an edit control is an edit control!
I would recommend to use Spy++ and check if and which messages are sent to the edit control. If no WM_USER messages arrive, it seems to be not connected to the CEditLog. Also some breakpoints in the CEditLog code might help to figure this out.
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Im having the same problem using CRichEditCtrl.
The problem seems to be with the values returned from GetScrollInfo.
Im working on a fix now.
|
|
|
|
|
Seems that GetScrollInfo may not return the correct information (well, correct for our purposes) if the scroll bar is not yet visible.
replace the following:
::GetScrollInfo( GetSafeHwnd(), SB_VERT, &si );
if( si.nPos >= si.nMax - (int) si.nPage + 1 )
with
::GetScrollInfo( GetSafeHwnd(), SB_VERT, &si );
if( si.nPos >= si.nMax - (int) si.nPage + 1 ||
!::GetScrollPos(GetSafeHwnd(), SB_VERT) )
GetScrollPos will return 0 on error (ie, the scroll bar is not visible). Note that I replaced the GetHandle calls with GetSafeHwnd (Im using a CRichEditCtrl)
|
|
|
|
|
sammyc wrote:
Seems that GetScrollInfo may not return the correct information (well, correct for our purposes) if the scroll bar is not yet visible.
replace the following:
::GetScrollInfo( GetSafeHwnd(), SB_VERT, &si );
if( si.nPos >= si.nMax - (int) si.nPage + 1 )
with
::GetScrollInfo( GetSafeHwnd(), SB_VERT, &si );
if( si.nPos >= si.nMax - (int) si.nPage + 1 ||
!::GetScrollPos(GetSafeHwnd(), SB_VERT) )
GetScrollPos will return 0 on error (ie, the scroll bar is not visible). Note that I replaced the GetHandle calls with GetSafeHwnd (Im using a CRichEditCtrl)
Thanks a lot about sharing your insights. Does it really work with rich edit controls now?
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Gives error:
fatal error C1001: INTERNAL COMPILER ERROR
|
|
|
|
|
Sorry for the late reaction...
It took some time to get VS2003, install it and so on. However, I finally found it out. Seems that VS2003 is much more hysterical of using types defined in templates with the typename keyword.
So go to line 125 and replace:
basic_editstreambuf< E, T, BUF_SIZE >::int_type basic_editstreambuf< E,T,BUF_SIZE >::overflow(
int_type c
)
with
typename basic_editstreambuf< E, T, BUF_SIZE >::int_type basic_editstreambuf< E,T,BUF_SIZE >::overflow(
int_type c
)
I am going to update the article project in the very next days.
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Still does not work. Even after repalcing this line, the sample project does not compile and gives internal compiler error.
|
|
|
|
|
Same here,
still not working
|
|
|
|
|
Hi all,
The updated demo project incorporates the changes I described in this thread. It now uses typename everywhere and compiles fine on VC.NET 2003.
(Boy, I hate this typename stuff. It bloats the source code a lot and nearly everything you refer from a template is a type! The standard comitee should have made types the default and introduced a no_type to destinguish template elemets that are no types...)
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Is there a possibility to restrict the number of lines?
So the buffer would not grow to "infinity" and you can only scroll back the last x lines.
I want to use it to log program actions, but I also write them to a log file. So it is not necessary to have all the lines in the buffer all the time.
I'm thinking about this, because my logfile can become very big.
But also without this functionality your CEditLog seems to be the best solution for my problem! Thanx!
|
|
|
|
|
I've been trying to get this to work effectively.... seems to be OK on a win2000/NT machine, but I've been having issues with it on win98.
Quite simply... when you're adding text, just do this too
nSize = (int) ::SendMessage( hEdit, WM_GETTEXTLENGTH, 0, 0 );
if ( nSize > MAX_TEXT_LEN ) {
::SendMessage( hEdit, EM_SETSEL, (WPARAM) 0, (LPARAM) TEXT_TRUNCATE_LEN );
if ( g_bIsWinNT ) {
::SendMessageW( hEdit, EM_REPLACESEL, 0, (LPARAM) "" );
} else {
::SendMessage( hEdit, EM_REPLACESEL, 0, (LPARAM) _W2A( (LPCWSTR) "" ) );
}
nSize = (int) ::SendMessage( hEdit, WM_GETTEXTLENGTH, 0, 0 );
}
Then use EM_SETSEL message with nSize params to set selection point to end of text.
Not 100% but worth a start for discussion purposes
|
|
|
|
|
Hi,
I had problem using your wonderful CEditLog class with a CEditView in a otherwise also strange environment (SDI app, multiple Views and the latest addition CEditLog with CEditView). The problem is, that the CEditView::OnDestroy handler isn't called and therefor the EditView doesn't tell the MainFrame to deactivate the CEditView during shutdown resulting in a crash.
As far as I have understood CSubclassWnd there is no chance to send a message to the subclassed window, after you called UnsubclassWindow (). So the subclassed CEditView doesn't see the message, since you call UnsublcassWindow within the WM_DESTROY handler.
The first solution I came up with was to call the DefWindowProc myself within the CEditLog::OnDestroy before you unsubclass the CEditCtrl
void CEditLog::OnDestroy()
{
DefWindowProc ();
UnsubclassWindow();
}
The second solution would be to remove the WM_DESTROY handling in CEditLog all together, since UnsubclassWindow is called during the WM_NCDESTROY handler from within CSublcassWnd anyway, naturally after the mesage has been passed to the subclassed window
There is this OnFinalMessage handler that you can use to do custom cleanup.
I would prefer the second solution, but I'm not sure why you introduced this handling of WM_DESTROY into your CEditLog. Perhaps some artifical relict.
As a second note: even if the following case handling will do no harm, I doesn't look like good coding style
case WM_ERASEBKGND:
if( m_bNoPaint )
return TRUE;
case WM_PAINT:
if( m_bNoPaint )
return TRUE;
You better combine those two cases and introduce a break. This is the funny behavoir if you introduce a further case statement and wonder why it is called in some strange situations.
Thanks for the class
Dirk
|
|
|
|
|
Thanks Dirk!
Very good points!
I would prefer the second solution, but I'm not sure why you introduced this handling of WM_DESTROY into your CEditLog. Perhaps some artifical relict.
To be honest - I don't know exactly why I am doing this. I assume it is still there because the original V1.0 of CSubclassWnd did not handle WM_NCDESTROY.
I will remove it in the next version
As a second note: even if the following case handling will do no harm, I doesn't look like good coding style
case WM_ERASEBKGND:
if( m_bNoPaint )
return TRUE;
case WM_PAINT:
if( m_bNoPaint )
return TRUE;
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
I am trying to display data from an array (lets just say a CString array) in a standard CEdit control with each item in the array on its own line. Is there a way to do this in a CEdit? I have tried to read the data into one big string with "\n"s between the items but this does not work. I am using SetWindowText() to display this data in the edit control. When I do that with "\n"s in the string, it just displays a "|" character where the line breaks are and keeps writing the rest of the text on the same line. There must be an easy way to do this. Please help!!!!!!
Newby,
Anthony
|
|
|
|
|
|
Perfect piece of code, especially because I needed the 'fast' thing since my debug-tool used this to handle a lot of data from several devices in a testbed.
Its based around Doc/View MDI architecture, where CEditLog is hooked into CEditView.
Now I've run into a small problem
When trying to print it cannot 'access' the textdata (and so crashes), and if saving the data, the file will be empty.
I do not have any clue where to start. Anyone a suggestion?
Thanks in advance
EiSl
|
|
|
|
|
Hm...
After a quick look into the sources of CEditView it seems that it sometimes uses a so-called "shadow buffer". This is needed on Win32s, but the code looks like it is also used on Win95 and derived systems. Maybe ths is the source for your problem.
I recommend to single step the save/print functions in your app and take a look where in the MFC sources they crash or fail.
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
Sooo. that's what I'm calling fast-support!
I was already afraid for this. I will start with the easy route first, which will be stepping through the 'Save' code.
The funny part of this all is... this morning my collega started with 'Murphy's Laws' jokes, and now I'm subject to it
I will keep you in touch )!
EiSl
|
|
|
|
|
Really great class ! I give it a 5.
I've added small helper class, CStreamRedirector , that handles stream attaching / detaching.
The typical use would be: create a CEditLog instance and a CStreamRedirector instance attached to the CEditLog . When redirection has to be turned on, call CStreamRedirector::Redirect(). To turn it off, UnRedirect(). The stream pointer mess cleaning is handled by CStreamRedirector
Here it is, if anybody interested
#include "EditLog.h"
#include "editlog_stream.h"
class CStreamRedirector
{
public:
CStreamRedirector(CEditLog& log);
virtual ~CStreamRedirector();
void Redirect();
void UnRedirect();
protected:
CEditLog& m_log;
bool m_bRedirect;
std::editstreambuf m_EditCout;
std::weditstreambuf m_EditWCout;
std::editstreambuf m_EditCerr;
std::weditstreambuf m_EditWCerr;
std::basic_streambuf< char >* m_pCout;
std::basic_streambuf< wchar_t >* m_pWCout;
std::basic_streambuf< char >* m_pCerr;
std::basic_streambuf< wchar_t >* m_pWCerr;
};
And here's the implementation
CStreamRedirector::CStreamRedirector(CEditLog& log)
: m_log(log), m_bRedirect(false),
m_EditCout(log), m_EditWCout(log), m_EditCerr(log), m_EditWCerr(log)
{
}
CStreamRedirector::~CStreamRedirector()
{
UnRedirect();
}
void CStreamRedirector::Redirect()
{
if (m_bRedirect)
return;
m_bRedirect=true;
m_pCout= std::cout.rdbuf( &m_EditCout);
m_pWCout= std::wcout.rdbuf( &m_EditWCout);
m_pCerr= std::cerr.rdbuf( &m_EditCerr);
m_pWCerr= std::wcerr.rdbuf( &m_EditWCerr);
};
void CStreamRedirector::UnRedirect()
{
if (!m_bRedirect)
return;
m_bRedirect=false;
std::cout.rdbuf( m_pCout);
std::wcout.rdbuf( m_pWCout);
std::cerr.rdbuf( m_pCerr);
std::wcerr.rdbuf( m_pWCerr);
};
Jonathan de Halleux.
|
|
|
|
|