问题的引入:
我希望在程序中有一个日志输出的窗口。最简单的就是在FORM上放一个LISTVIEW。然后程序各地调用日志输出的时候,在这个LISTVIEW中可以将日志写上去。
就像
LogForm1->WriteLog("系统消息...");
就像我有三个工程:
MainUI :界面展示
DataProc :数据和业务的处理
msql :mysql封装
其构建关系和依赖关系是mysql独立,DataProc依赖于mysql, MainUI依赖于DataProc。
出于洁癖的考虑,DataProc没有界面。MainUI中可以放一个输出日志的Form。
显然DataProc再扭过头来use MainUI实在是强人所难。
so,DataProc发送一个WindowsMessage给界面,通过SendMessage让界面展示就好了。
这里边涉及System::String转换,new一个buffer,然后由接收端收到后展示完free。
CmdbLog::CmdbLog(void *pHwnd,UINT wm_id) { m_MainHwnd = (HWND)pHwnd; m_MessageID = wm_id; } void CmdbLog::WriteLog(System::String ^ pString,...array<System::Object ^>^pOArray) { pin_ptr<const wchar_t> wch = PtrToStringChars(pString); char *pc; int ipc; System::String ^ o; o = System::String::Format(pString,pOArray); ipc = wcslen(wch) + 1; ipc *= sizeof(wchar_t); pc = new char[ipc]; memcpy(pc,wch,ipc); ::SendMessage(m_MainHwnd,m_MessageID,0,(LPARAM)pc); }
主Form(LogForm中响应这个消息)
const UINT wm_LogMessageID = ::RegisterWindowMessageA( "LOGEVENT" );
[SecurityPermission(SecurityAction::Demand, Flags=SecurityPermissionFlag::UnmanagedCode)]
virtual void WndProc( Message% m ) override //重载窗口过程处理消息
{
if( m.Msg == wm_LogMessageID)
{
System::String^ m_sShowMessageString;
m_sShowMessageString = gcnew System::String((const wchar_t*)(void*)m.LParam);
MessageBox::Show(m_sShowMessageString); //接收自定义消息 并处理
AddLogRow(m_sShowMessageString);
delete [] (char*)(void*)m.LParam; // 释放这个buffer
}
Form::WndProc( m );
}
m_vars->InitCmdbLog((void*)this->Handle,wm_LogMessageID);void Form1::AddLogRow(System::String^ pString){ array<System::String^> ^ pItem = pString->Split(',',':'); array<System::String^> ^ps = gcnew array<System::String^>(2); System::Windows::Forms::ListViewItem^pListViewItem; if (pItem->Length > 1) { ps[0] = pItem[0]; ps[1] = pString->Substring(pItem[0]->Length + 1, pString->Length - pItem[0]->Length -1); } else { ps[0] = "缺省"; ps[1] = pString; } pListViewItem = gcnew System::Windows::Forms::ListViewItem(ps,-1); listView1->BeginUpdate(); listView1->Items->Add(pListViewItem); listView1->EndUpdate(); }