前言:
日前,师兄交给了我一个课题,将一个后台运行的Console程序,修改为WindowsForm程序,并在其界面上增加配置设置,以及运行记录。
原来的Console程序,后台运行的流程在其中一个类的函数里。我在我创建的主窗体上创建这个类的对象,然后执行它的函数。结果就遇到了一个问题,大部分需要记录下的运行记录,都是在这个类的函数中,而这个类怎么去访问我的主窗体上的RichTextBox呢?
我尝试了下设置RichTextBox为Public,结果还是不能在外面的类调用它,尝试设置WinForm为Static这种蠢方法,也只是使过程变得原来越复杂。
最后决定使用我最不想用的Windows消息方式(因为以前觉得比较麻烦)。虽然用的过程中有些存在风险,并且特别不专业,但是总之是达到了我想要的结果,也算是一个进步吧。
1
2
|
[DllImport(
"User32.dll"
, EntryPoint =
"SendMessage"
)]
private
static
extern
IntPtr SendMessage(
int
hWnd,
int
msg, IntPtr wParam, IntPtr lParam);
|
当然,在使用过程中要用到这个SendMessage,具体的使用方法,参照http://blog.sina.com.cn/s/blog_90b91bf10100zj77.html,虽然有点问题,但是大体上是正确的。
但是这个还不足以实现我的需求,因为我需要传递的是字符串,是string,而消息里面的两个参数wParam是IntPtr。在网上找了好一阵之后,发现这两篇文章很有指导意义:http://blog.csdn.net/lanruoshui/article/details/5432891和http://blog.csdn.net/lanruoshui/article/details/5432953(同一个人写的,两篇文章有关联,主要是第二篇)。
主体:
首先,发送端在声明API函数的时候,直接声明wParam和lParam为string(不知道这么做有没有风险,但是确实没有报错……而且管用)
1
2
3
4
|
[DllImport(
"User32.dll"
, EntryPoint =
"SendMessage"
)]
private
static
extern
IntPtr SendMessage(
int
hWnd,
int
msg,
string
wParam,
string
lParam);
[DllImport(
"User32.dll"
, EntryPoint =
"FindWindow"
)]
private
static
extern
int
FindWindow(
string
lpClassName,
string
lpWindowName);
|
然后,封装一个发送消息的函数SendMsgToMainForm,以便调用。这一部分与正常用法基本无异,需要注意封装的函数也需要修改参数属性为string。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//定义消息常数
public
const
int
CUSTOM_MESSAGE = 0X400 + 2;
//自定义消息
public
const
int
COMMAND_MESSAGE = 0X400 + 3;
//指令消息
//向窗体发送消息的函数
public
void
SendMsgToMainForm(
int
MSG,
string
awParam,
string
alParam)
{
int
WINDOW_HANDLER = FindWindow(
null
, Factory.FormName);
if
(WINDOW_HANDLER == 0)
{
throw
new
Exception(
"Could not find Main window!"
);
}
SendMessage(WINDOW_HANDLER, MSG, awParam, alParam);
//立即执行此消息
Application.DoEvents();
}
|
重点在接收端,也就是定义窗体的地方。使用string str = Marshal.PtrToStringAnsi(msg.WParam);//托管Marshal,把WParam托管为可以直接使用的string。这样一个字符串消息就传递过来了。调用窗体的WriteLog函数,来完成运行记录的记录。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
protected
override
void
WndProc(
ref
System.Windows.Forms.Message msg)
{
string
str = Marshal.PtrToStringAnsi(msg.WParam);
//托管Marshal
switch
(msg.Msg)
{
case
ICBC_BankChecking.CUSTOM_MESSAGE:
//处理消息
{
this
.WriteLog(str);
}
break
;
case
ICBC_BankChecking.COMMAND_MESSAGE:
{
switch
(str)
{
case
"00"
:
SetPage(
true
);
break
;
}
}
break
;
default
:
base
.WndProc(
ref
msg);
//调用基类函数处理非自定义消息。
break
;
}
}
|