当前位置:主页>仓库管理软件> 列表

请教一个消息传递的问题 找erp系统软件有哪些

记账软件版1楼: const
WM_MYMSG=WM_USER+100;
type
TForm1=class(TForm)
...
public
procedure WMMYMSG(var msg:TMessage); message WM_MYMSG;
end;

implementions

procedure TForm1.WMMYMSG(var Msg: TMessage);
var
p:TPoint;
begin
case [red]msg.LParam [/red]of
WM_RBUTTONDOWN:
....
WM_MOUSEMOVE:
....
WM_LBUTTONUP:
....
end;
end;

我不明的是为何在case语句中是用msg.Lparam的值来判断?而不是用msg.msg或msg.WParam来进行判断是什么消息?如何才知道消息的值是放在msg的哪个字段里面?

2楼: 通过
const
WM_MYMSG=WM_USER+100;
知道你这个消息是自定义的

至于判断msg.Lparam 要看发送的代码是怎么配置 光靠瞪眼法恐怕看不出来吧 如erp系统软件有哪些

3楼: 能举个例子吗?

我是想在窗口缩小时将图标放到托盘中,托盘数据结构的中回调消息就是WM_MYMSG。
按您上面所述“要看发送的代码是怎么配置”,如何来知道是用MSG的哪个字段来判断消息值?

4楼: 原来是做托盘啊



实际上你托盘向进程
发送 类似这样的消息
Sendmessage(Self.Handle, WM_MYMSG, 0 ,WM_MOUSEMOVE);

为什么判断msg.Lparam 实际是微软实现定义好的 具体你可以查看MSDN

5楼: 但鼠标移动到托盘上的图标时,会自动触发wm_mymessage消息进行回调,但为何是用msg的lparam字段来判断消息值,为何不是msg.msg或msg.wparam字段呢?
我看了MSDN,上面只是解释了这三个字段的意思,并没说到类似上面的问题。

uCallbackMessage
Application-defined message identifier. The system uses this identifier to send notifications to the window identified in hWnd. These notifications are sent when a mouse event occurs in the bounding rectangle of the icon, or when the icon is selected or activated with the keyboard. [red]The wParam parameter of the message contains the identifier of the taskbar icon in which the event occurred. The lParam parameter holds the mouse or keyboard message associated with the event.[/red] For example, when the pointer moves over a taskbar icon, lParam is set to WM_MOUSEMOVE. See the Taskbar guide chapter for further discussion.

我看Shell_notify这个API函的参考时,看到回调消息的解释。其中WParam的参数是在事件发生时包含任务栏图标的标识?这是什么意思是指应用程序在托盘中图标的标识?也就是那个UID吗?
uID
Application-defined identifier of the taskbar icon. The Shell uses hWnd and uID to identify which icon to operate on when Shell_NotifyIcon is invoked. You can have multiple icons associated with a single hWnd by assigning each a different uID.
这个uID起个什么作用呢?

6楼: 理论:
系统托盘是指任务条中的一个方形区域,在该区域中可以放入一些小图标,通常您可以在此处看到系统提供的最新时间。您自己当然也可以把快捷小图标放到此处。下面是这么做的步骤:
设置NOTIFYICONDATA型的结构体变量的成员变量的值:
cbSize 该结构体的大小。
hwnd 窗口的句柄。当鼠标滑过该小图标时,该窗口将接收到相关的消息。
uID 小图标的ID号。您可以取任意值,只是当您的应用程序有不止一个小图标时,您要能够区分出到底是那一个小图标接收到了鼠标的消息,也即ID号必须唯一。
uFlags 指定该结构体变量的那些成员变量有效。
NIF_ICON 有效。
NIF_MESSAGE 有效。


NIF_TIP 有效。
uCallbackMessage 自定义的消息。当鼠标对小图标动作时,WINDOWS外壳将把该消息发送到您的应用程序。该消息的值您可以自己定义。
hIcon 放入系统托盘中的图标的句柄。
szTip 64字节的缓冲区,它用来放入提示字符串,当鼠标停留在小图标上时,就会显示该字符串。
调用Shell_NotifyIcon函数。该函数在shell32.inc中定义,其原型如下:

Shell_NotifyIcon PROTO dwMessage:DWORD ,pnid:DWORD

dwMessage 是发送到WINDOWS外壳的消息:
NIM_ADD 把小图标加到系统托盘区。
NIM_DELETE 从系统托盘中删除小图标。
NIM_MODIFY 修改小图标。
pnid 是指向NOTIFYICONDATA型结构体变量的指针。
如果您想要加入一个小图标就用NIM_ADD,删除时使用NIM_DELETE消息。

基本上的消息就是这些。但是大多数的情况下,您不会仅仅满足把一个小图标放到那里。您还必须要对鼠标事件作出适当的反应。您可以在NOTIFYICONDATA型的结构体变量的成员变量uCallbackMessage 中设置您要处理的消息,然后WINDOWS外壳将在发生这些事件时通知您的应用程序。随着消息传送的参数wParam和lParam的值如下:
wParam 小图标的ID号。它和您在NOTIFYICONDATA型结构体变量中的成员变量uID中设置的值一样。

lParam 低字包含鼠标消息。譬如,用户在小图标上按下了右键时,lParam中将包含WM_RBUTTONDOWN消息。
大多数的系统托盘中的小图标,在用户用鼠标右击时都会弹出一个菜单以方便用户选择。我们可先创建菜单,然后调用TrackPopupMenu函数来显示它。步骤如下:
调用CreatePopupMenu函数来创建菜单。该函数创建一个空的菜单。如果成功,将在eax中返回该菜单的句柄。
调用AppendMenu, InsertMenu 或 InsertMenuItem来向菜单中加入菜单项。
当您想在当前鼠标位置显示该菜单时,调用GetCursorPosition函数来得到鼠标当前的屏幕位置,然后调用TrackPopupMenu来显示菜单。当用户从弹出式菜单中选择了一个菜单项时,WINDOWS将发送WM_COMMAND消息给您应用程序的消息处理过程,这和通常的菜单选择是一样的。.
注意:当您使用系统托盘中的小图标时有两件比较讨厌的事:
该菜单可能不会像通常那样马上消失掉。这是因为从弹出式接收消息的窗口必须是前景窗口。调用SetForegroundWindow函数就可以纠正该错误;
在调用了SetForegroundWindow函数后,您会发现第一次该弹出式菜单会正常弹出而且工作的很好。但是随后,该菜单只是一弹出就立即消失。根据MSDN,这么做是故意的。为了使得弹出菜单保持住,必须要求下一个切换到的是程序的主窗口。您可以通过邮寄任何消息给该程序的窗口来强行进行任务切换。注意要使用PostMessage而不是SendMessage。

记账软件版7楼: 大侠,有QQ号或MSN吗?我的是21200151
有空还想向你请教一些问题?不知是否方便?

另外,您上面所述的“应用程序有不止一个小图标时?”是指应用程序在托盘中有多个图标吗?

8楼: 我不明的是为何在case语句中是用msg.Lparam的值来判断?
具体用什么来判断要看具体是什么消息,
给你个例子既用到了wparam,又用到了lparam
建议看一看<>这本书,我是初学者,我也正在看,上面写得很清楚.
还要看MSDN,或者Delphi自带的SDK帮助.
给你个例子既用到了wparam,又用到了lparam

program SysMets4;

uses
Windows, Messages, Math, SysMets;

// 窗体消息处理回调函数
function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
const
{$J+}
cxChar: Integer = 0; // 小写字母宽度
cxCaps: Integer = 0; // 大写字母宽度
cyChar: Integer = 0; // 小写字母高度
cxClient: Integer = 0; // 窗体客户区宽度
cyClient: Integer = 0; // 窗体客户区高度
iMaxWidth: Integer = 0; // 文字输出行宽度
{$J-}
var
X, Y, J, L, iVertPos, iHorzPos, iPaintBeg, iPaintEnd: Integer;


Buffer: array [0..5] of Char; // 输出缓冲区
hWndDc: HDC;
PS: TPaintStruct;
TM: TTextMetric;
SI: TScrollInfo;
begin
Result := 0;
case Msg of
WM_CREATE : begin
hWndDc := GetDC(hWnd);

GetTextMetrics(hWndDc, TM); // 取得字体度量信息
cxChar := TM.tmAveCharWidth;
if (TM.tmPitchAndFamily and $1) = 0 // 宽度固定?
then cxCaps := cxChar
else cxCaps := cxChar * 3 div 2;
cyChar := TM.tmHeight + TM.tmExternalLeading;
iMaxWidth := 40 * cxChar + 22 * cxCaps;

ReleaseDC(hWnd, hWndDc);
end;

WM_SIZE : begin
cxClient := LOWORD(lParam);
cyClient := HIWORD(lParam);
// 设置竖直卷动条范围和单页大小
SI.cbSize := SizeOf(SI);
SI.fMask := SIF_RANGE or SIF_PAGE;

SI.nMin := 0;
SI.nMax := NUMLINES - 1;
SI.nPage := cyClient div cyChar;
SetScrollInfo(hWnd, SB_VERT, SI, TRUE);
// 设置横向卷动条范围和单页大小
SI.cbSize := SizeOf(SI);
SI.fMask := SIF_RANGE or SIF_PAGE;
SI.nMin := 0;
SI.nMax := 2 + iMaxWidth div cxChar;
SI.nPage := cxClient div cxChar;
SetScrollInfo(hWnd, SB_HORZ, SI, TRUE);
end;

WM_VSCROLL : begin
// 取得竖直卷动条全部信息
SI.cbSize := SizeOf(SI);
SI.fMask := SIF_ALL;
GetScrollInfo(hWnd, SB_VERT, SI);
// 暂存竖直卷动条位置信息
iVertPos := SI.nPos;
// 区分不同的卷动类型
case LOWORD(wParam) of
SB_TOP : SI.nPos := SI.nMin;
SB_BOTTOM : SI.nPos := SI.nMax;
SB_LINEUP : SI.nPos := SI.nPos-1;
SB_LINEDOWN : SI.nPos := SI.nPos+1;
SB_PAGEUP : SI.nPos := SI.nPos-SI.nPage;
SB_PAGEDOWN : SI.nPos := SI.nPos+SI.nPage;
SB_THUMBTRACK: SI.nPos := SI.nTrackPos;
end;
SI.fMask := SIF_POS;
SetScrollInfo(hWnd, SB_VERT, SI, TRUE);
GetScrollInfo(hWnd, SB_VERT, SI);
// 与以前不同则上下滚动(产生无效区域)
if (SI.nPos <> iVertPos) then
begin
ScrollWindow(hWnd, 0, cyChar * (iVertPos - SI.nPos), nil, nil);
UpdateWindow(hWnd);
end;
end;

WM_HSCROLL : begin
// 取得横向卷动条全部信息
SI.cbSize := SizeOf(SI);
SI.fMask := SIF_ALL;
GetScrollInfo(hWnd, SB_HORZ, SI);
// 暂存横向卷动条位置信息
iHorzPos := SI.nPos;
// 区分不同的卷动类型
case LOWORD(wParam) of
SB_LINELEFT : SI.nPos := SI.nPos-1;
SB_LINERIGHT : SI.nPos := SI.nPos+1;
SB_PAGELEFT : SI.nPos := SI.nPos-SI.nPage;
SB_PAGERIGHT : SI.nPos := SI.nPos+SI.nPage;
SB_THUMBPOSITION: SI.nPos := SI.nTrackPos;
end;
SI.fMask := SIF_POS;
SetScrollInfo(hWnd, SB_HORZ, SI, TRUE);
GetScrollInfo(hWnd, SB_HORZ, SI);
// 与以前不同则左右滚动(产生无效区域)
if (SI.nPos <> iHorzPos) then
begin
ScrollWindow(hWnd, cxChar * (iHorzPos - SI.nPos), 0, nil, nil);

UpdateWindow(hWnd);
end;
end;

WM_KEYDOWN : begin // 转发滚动消息
case wParam of
VK_HOME : SendMessage(hWnd, WM_VSCROLL, SB_TOP, 0);
VK_END : SendMessage(hWnd, WM_VSCROLL, SB_BOTTOM, 0);
VK_PRIOR : SendMessage(hWnd, WM_VSCROLL, SB_PAGEUP, 0);
VK_NEXT : SendMessage(hWnd, WM_VSCROLL, SB_PAGEDOWN, 0);
VK_UP : SendMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0);
VK_DOWN : SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0);
VK_LEFT : SendMessage(hWnd, WM_HSCROLL, SB_PAGEUP, 0);
VK_RIGHT : SendMessage(hWnd, WM_HSCROLL, SB_PAGEDOWN, 0);
end;
end;

WM_PAINT : begin
hWndDc := BeginPaint(hWnd, PS);

SI.cbSize := SizeOf(SI) ;


SI.fMask := SIF_POS;
// 取得竖直卷动条位置
GetScrollInfo(hWnd, SB_VERT, SI);
iVertPos := SI.nPos ;
// 取得横向卷动条位置
GetScrollInfo(hWnd, SB_HORZ, SI);
iHorzPos := SI.nPos;
// 计算需要重绘的范围(行)
iPaintBeg := Max(0, iVertPos + PS.rcPaint.Top div cyChar);
iPaintEnd := Min(NUMLINES - 1, iVertPos + PS.rcPaint.Bottom div cyChar);
// 依次绘制各行
for J := iPaintBeg to iPaintEnd do
begin
X := cxChar * (1 - iHorzPos); // 本行横坐标(左上角)
Y := cyChar * (J - iVertPos); // 本行纵坐标(左上角)
TextOut(hWndDc, X, Y, SysMetrics[J].szLabel, lstrlen(SysMetrics[J].szLabel));
TextOut(hWndDc, X + 22 * cxCaps, Y, SysMetrics[J].szDesc, lstrlen(SysMetrics[J].szDesc));
SetTextAlign(hWndDc, TA_RIGHT or TA_TOP); // 右上对齐
L := GetSystemMetrics(SysMetrics[J].Index);
TextOut(hWndDc, X + 22 * cxCaps + 40 * cxChar , Y, Buffer, wvsprintf(Buffer, ''%5d'', @L));
SetTextAlign(hWndDc, TA_LEFT or TA_TOP); // 左上对齐
end;

EndPaint(hWnd, PS);
end;

WM_DESTROY : PostQuitMessage(0); // 退出循环

else Result := DefWindowProc(hWnd, Msg, wParam, lParam); // 默认处理
end;
end;


const
AppName = ''SysMets4'';

var
hWnd: LongWord;
Msg: TMsg;
WndClass: TWndClass;

begin
// 填充结构体
WndClass.style := CS_HREDRAW or CS_VREDRAW;
WndClass.lpfnWndProc := @WndProc;
WndClass.cbClsExtra := 0;
WndClass.cbWndExtra := 0;
WndClass.hInstance := hInstance;
WndClass.hIcon := LoadIcon(0, IDI_APPLICATION);
WndClass.hCursor := LoadCursor(0, IDC_ARROW);
WndClass.hbrBackground := GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName := nil;
WndClass.lpszClassName := AppName;

// 注册窗体类
if (RegisterClass(WndClass) = 0) then
begin
MessageBox(0,''Program requires Windows NT!'', AppName, MB_ICONERROR);
Exit;
end;

// 建立窗体
hWnd := CreateWindow(AppName, ''Get System Metrics No. 4'',
WS_OVERLAPPEDWINDOW or WS_VSCROLL or WS_HSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, hInstance, nil);

// 显示窗体
ShowWindow(hWnd, CmdShow);
UpdateWindow(hWnd);

// 消息循环
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end.

9楼: 欣赏楼主的钻研精神 呵呵

10楼: 有不对的地方,楼下大虾扶正

11楼: 呵。。。很感谢二位富翁的指点,用哪个字段来判断,看样子还是要多看MSDN上的帮助了,比如WM_SYSCOMMAND这个消息,在处理时,就要用WPARAM这个字段来进行判断,在MSDN上说的很详细了,我开始也没有认真看,因为全是英文的,后来在AVALON大侠提到看MSDN,我才又仔细查看了一下,果真上面对托盘回调消息讲得比较清楚了。呵。。看样子,还是得多多学习英文呀,,《windows程序设计》这本书我也看了,但还是有些地方写得不太详细,自己在编程时对消息处理起来还是觉得有些吃力,有空还请二位大侠多多指点,谢谢!