首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

使用API怎么写出稳定的系统托盘程序

2012-02-13 
使用API如何写出稳定的系统托盘程序?我想要写一个系统托盘程序,只需要显示一个小图标,然后如果用右键点击

使用API如何写出稳定的系统托盘程序?
我想要写一个系统托盘程序,只需要显示一个小图标,然后如果用右键点击一下就弹出一个菜单,找到了一段这样的代码,我试验过后发现这样确实可以实现我想要的功能,但是程序运行一、两个小时后右键菜单就显示不出来了,在显示不出右键菜单时TrackPopupMenu函数虽然返回True,但是我通过GetLastError函数发现有错误ERROR_INVALID_HANDLE,而前面CreatePopupMenu却没有任何错误。代码中的MyDll.dll只需要LoadLibrary就会开启两个线程用TextOutA函数在屏幕上不断的输出文字。
program Shell;

uses
  Windows,ShellAPI,Messages,SysUtils;

{$R ShellCPU.res}
const
  ClassName='myownclassname';

var
  msg:TMsg;
  WndClass:TWndClassA;
  hWnd,hPop:THandle;
  hMap:THandle;
  pBool:Pointer;
  ShowUsage:BOOL;
  WM_TASKBARCREATED:Cardinal;
  PopText:PChar;
  NotifyData: NOTIFYICONDATA;
  bInit:BOOL;
procedure Shell_AddICON(Add:Boolean=True);
begin
  with NotifyData do
  begin
  cbSize:=SizeOf(NotifyData);
  Wnd:=hWnd;
  uID:= 0;
  uFlags:=NIF_MESSAGE or NIF_ICON;
  uCallbackMessage:=WM_USER+888;
  end;
  if Add then
  Shell_NotifyIcon(NIM_ADD,@NotifyData)
  else
  Shell_NotifyIcon(NIM_DELETE,@NotifyData);
end;
procedure InitShare;
begin
  hMap:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(Bool),'myinformation');
  pBool:=MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);
  CopyMemory(pBool,@ShowUsage,SizeOf(BOOL));
end;

procedure WriteShare;
begin
  CopyMemory(pBool,@ShowUsage,SizeOf(BOOL));
end;  

function MainWndProc(HWin: THandle; MsgID: UINT; wParam, lParam: Integer): LRESULT; stdcall;
var
  iButton:Integer;
  hdcS:HDC;
  dwErr:DWORD;
  tpCurrentPoint:TPoint;
begin
  case MsgID of
  WM_CREATE:
  begin
  WM_TASKBARCREATED:=RegisterWindowMessage('TaskbarCreated');
  end;  
  WM_CLOSE:
  begin
  UnmapViewOfFile(pBool);
  CloseHandle(hMap);
  DestroyWindow(hWnd);
  end;
  WM_DESTROY:
  begin
  PostQuitMessage(0);
  end;
  WM_USER+888:
  begin

  if ((wParam=0) and (lParam=$201)) then
  begin
  ShowUsage:=not ShowUsage;
  WriteShare;
  end;
  if ((wParam=0) and (lParam=$205)) then//在图标上按了右键
  begin
  hPop:=CreatePopupMenu;
  AppendMenu(hPop,MF_STRING,1,'退出');
  AppendMenu(hPop,MF_SEPARATOR,9,nil);
  SetForegroundWindow(HWin);
  GetCursorPos(tpCurrentPoint);
  if ShowUsage=True then
  PopText:=PChar('不显示')
  else
  PopText:=PChar('显示');
  AppendMenu(hPop,MF_CHANGE or MF_STRING,2,PopText);
  iButton:=Integer(TrackPopupMenu(hPop,
  TPM_LEFTALIGN or TPM_LEFTBUTTON,
  tpCurrentPoint.X,
  tpCurrentPoint.y,
  0,
  hWnd,
  nil));
  DestroyMenu(hPop);
  end;
  end;
  end;
  if MsgID= WM_COMMAND then
  begin
  iButton:=wParam;
  if iButton=1 then
  begin
  Shell_AddICON(False);
  ExitProcess(0);
  end
  else if iButton=2 then
  begin
  ShowUsage:=not ShowUsage;
  WriteShare;
  if ShowUsage then
  NotifyData.hIcon:=LoadIcon(HInstance,'TRAYH')
  else
  NotifyData.hIcon:=LoadIcon(HInstance,'TRAYS');


  end;
  Shell_NotifyIcon(NIM_MODIFY,@NotifyData);
  end;
  if MsgID=WM_TASKBARCREATED then
  begin
  Shell_AddICON;
  end;  
  Result:=DefWindowProc(HWin,MsgID,wParam,lParam);
end;

begin
  if ParamStr(1)='f' then
  begin
  ShowUsage:=False;
  NotifyData.hIcon:=LoadIcon(HInstance,'TRAYS');
  end

  else
  begin
  ShowUsage:=True;
  NotifyData.hIcon:=LoadIcon(HInstance,'TRAYH');
  end;  

  with WndClass do
  begin
  style:=CS_HREDRAW or CS_VREDRAW;
  lpfnWndProc:=@MainWndProc;
  hInstance:= sysinit.HInstance;
  hIcon:=LoadIcon(0,PChar(IDI_APPLICATION));
  hCursor:=LoadCursor(0,IDC_ARROW);
  hbrBackground:=GetStockObject(WHITE_BRUSH);
  lpszClassName:=ClassName;
  end;
  if RegisterClass(WndClass)=0 then
  ExitProcess(0);
  hWnd:=CreateWindowEx(0,PChar(ClassName),'Shell',WS_OVERLAPPED,0,0,100,100,0,0,hInstance,nil);
  if hWnd=0 then
  begin
  MessageBox(0,'无法创建窗口!','错误',0);
  ExitProcess(0);
  end;
  InitShare;
  Shell_AddICON;
  LoadLibrary('MyDll.dll');
  while GetMessage(msg,0,0,0) do
  begin
  TranslateMessage(msg);
  DispatchMessage(msg);
  end;
end.

[解决办法]
CoolTrayIcon VCL组件源码是公开的,可以下载一个看一下。
[解决办法]
如好用请结贴快一点

热点排行