如何理解SHELL_NODIFYICON的使用(100分)

  • 主题发起人 主题发起人 faun
  • 开始时间 开始时间
F

faun

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在手边无MSDN,不知shell_nodifyicon的参数定义,<br>求助于各位了。
 
Sends a message to the system to add, modify, or delete an icon from the taskbar status area.<br><br>WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(<br><br>&nbsp; &nbsp; DWORD dwMessage, // message identifier<br>&nbsp; &nbsp; PNOTIFYICONDATA pnid // pointer to structure<br>&nbsp; &nbsp;); <br>&nbsp;<br><br>Parameters<br><br>dwMessage<br><br>Identifier of the message to send. This parameter can be one of these values:<br><br>NIM_ADD Adds an icon to the status area.<br>NIM_DELETE Deletes an icon from the status area.<br>NIM_MODIFY Modifies an icon in the status area. <br>&nbsp;<br><br>pnid<br><br>Pointer to a NOTIFYICONDATA structure. The content of the structure depends on the value of <br>dwMessage. <br><br>&nbsp;<br><br>Return Values<br><br>If the function succeeds, the return value is nonzero.<br>If the function fails, the return value is zero.<br><br><br>Contains information that the system needs to process taskbar status area messages.<br><br>typedef struct _NOTIFYICONDATA { // nid &nbsp;<br>&nbsp; &nbsp; DWORD cbSize; <br>&nbsp; &nbsp; HWND hWnd; <br>&nbsp; &nbsp; UINT uID; <br>&nbsp; &nbsp; UINT uFlags; <br>&nbsp; &nbsp; UINT uCallbackMessage; <br>&nbsp; &nbsp; HICON hIcon; <br>&nbsp; &nbsp; char szTip[64]; <br>} NOTIFYICONDATA, *PNOTIFYICONDATA; <br>&nbsp;<br><br>Members<br><br>cbSize<br><br>Size of the NOTIFYICONDATA structure.<br><br>hWnd<br><br>Handle of the window that receives notification messages associated with an icon in the taskbar status area. <br><br>uID<br><br>Application-defined identifier of the taskbar icon.<br><br>uFlags<br><br>Array of flags that indicate which of the other members contain valid data. This member can be a combination of these values:<br><br>NIF_ICON The hIcon member is valid. <br>NIF_MESSAGE The uCallbackMessage member is valid.<br>NIF_TIP The szTip member is valid.<br>&nbsp;<br><br>uCallbackMessage<br><br>Application-defined message identifier. The system uses the specified identifier for notification messages that it sends to the window identified by hWnd whenever a mouse event occurs in the bounding rectangle of the icon. <br><br>hIcon<br><br>Handle of the icon to add, modify, or delete. <br><br>szTip<br><br>Tooltip text to display for the icon.<br><br>&nbsp;<br>
 
看这里,中文的. &nbsp; &nbsp;{B-)<br><br>http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=200349
 
安装了bcb或者delphi后<br>在 borland/borland shared/mshelp/win32.hlp 就有win32 api的帮助,<br>不是什么都要msdn<br>
 
在 cbuilder4/help/bcb4.cnt (c++ builder 4)<br>或者<br>在 delphi4(或者5)/help/delphi4(或者5).cnt (delphi 4/5)<br><br>加上一行:<br>:index win32=c:/borland(你的安装目录)/borland shared/mshelp/win32.hlp<br><br>就可以在你的bcb或者delphi的在线帮助看到win32的帮助了
 
不过不可全信delphi的win32 api帮助, 有些有误.<br>我发现了一个: EM_POSFROMCHAR, win32.hlp和MSDN上说的完全是<br>两码事. 不幸的是MSDN上的正确. <br>delphi的help浪费了我4小时, 并且促使我干了一件非常无聊的事: 从低层开<br>始整个重写了一个windows的edit control.
 
CSDN上好象有个详细的例子<br>我就是在那里学会的
 
delphi带来的win32.hlp也是ms的sdk提供的,只是ms那个时候搞错了而已。<br>只是你的msdn比hlp要新一点,要是找个和hlp同时间的msdn,肯定也是错的<br><br>hlp绝大多数东西还是对的嘛,msdn太大,也不如hlp方便用
 
&nbsp; &nbsp;从技术方面来说,一个任务栏应用程序非常象普通的应用程序,它有一个消息循环,相应windows的消息来完成相应的功能。 <br><br>procedure runtrayapplication;<br>var msg : tmsg;<br>begin<br>&nbsp; createwindow;<br>&nbsp; addtrayicon;<br>&nbsp; while getmessage(msg,0,0,0) do begin<br>&nbsp; &nbsp; translatemessage(msg);<br>&nbsp; &nbsp; dispatchmessage(msg);<br>&nbsp; end;<br>&nbsp; deletetrayicon;<br>end;<br>&nbsp; &nbsp; 你能看到:所有需要做的工作是创建一个窗口,注册一个图标到任务栏,设置它的消息循环,最后关闭它。当然,必须还有增加其他代码完成相应的功能,但是,它是真的不需要担心。 <br><br>&nbsp; &nbsp; 让我们从窗口的创建开始。实际上,这个窗口是不是能在任务栏上能见到的窗口。相应的,这个窗口只是处理消息循环、其它父类的工作。任务窗口(windows 95 &amp; nt)句柄创建消息(例如鼠标单击等)和将消息发到我们的窗口。 <br><br>procedure createwindow;<br>var<br>&nbsp; wc : twndclass;<br>&nbsp; w &nbsp;: hwnd;<br>begin<br>&nbsp; with wc do begin<br>&nbsp; &nbsp; style := 0;<br>&nbsp; &nbsp; lpfnwndproc := @wndproc;<br>&nbsp; &nbsp; cbclsextra := 0;<br>&nbsp; &nbsp; cbwndextra := 0;<br>&nbsp; &nbsp; hicon := 0;<br>&nbsp; &nbsp; hcursor := 0;<br>&nbsp; &nbsp; hbrbackground :=di2001.jpg;<br>&nbsp; &nbsp; lpszmenuname := nil;<br>&nbsp; &nbsp; lpszclassname := 'mytrayiconclass';<br>&nbsp; &nbsp; hinstance := system.hinstance;<br>&nbsp; end;<br>&nbsp; registerclass(wc);<br>&nbsp; w := windows.createwindow('mytrayiconclass', 'myveryowntrayiconwindow',<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ws_overlappedwindow, 0, 0, 0, 0, 0, 0, hinstance, nil);<br>&nbsp; showwindow(w,sw_hide);<br>&nbsp; updatewindow(w);<br>&nbsp; mainwindow := w;<br>end;<br> <br><br>&nbsp; &nbsp; 这个窗口使用普通的窗口函数创建。注意这个窗口的类型是“ws_overlappedwindow”,但是这个尺寸是0,并且它是隐藏的,所有,它将不会显示出来。 <br><br>&nbsp; &nbsp; 下一步是加(注册)我们的图标。这将需要使用shell_notifyicon这个api函数,这个函数实际上可以完成三个功能,这里只需要它的增加的特性。 <br><br>procedure addtrayicon;<br>var icondata : tnotifyicondata;<br>begin<br>&nbsp; with icondata do begin<br>&nbsp; &nbsp; cbsize := sizeof(icondata);<br>&nbsp; &nbsp; wnd := mainwindow;<br>&nbsp; &nbsp; uid := 0;<br>&nbsp; &nbsp; uflags := nif_icon or nif_message or nif_tip;<br>&nbsp; &nbsp; ucallbackmessage := wm_mycallback;<br>&nbsp; &nbsp; hicon := loadicon(hinstance,'myicon');<br>&nbsp; &nbsp; strcopy(sztip,pchar(trayicontip));<br>&nbsp; end;<br>&nbsp; shell_notifyicon(nim_add,@icondata);<br>end;<br> <br><br>&nbsp; &nbsp; 这个最重要的事情是tnotifyicondata的数据结构,它是一个设置window句柄的数据结构,是一个记录参数,对我们来说,我们需要设置这个图标的窗口句柄(这将定义哪个窗口处理消息循环),回调消息号,图标,工具提示等。一旦这个数据设置了,我们就可以增加一个图标到任务栏上了。为了完成这个工作,使用nim_add程序。 <br><br>&nbsp; &nbsp; 现行我们已经加了我们的图标到任务栏,下面需要决定如何处理消息。 <br><br>const<br>&nbsp; wm_mycallback = wm_user+1000;<br>&nbsp; cm_exit &nbsp; &nbsp; &nbsp; = 100; { we worry about... }<br>&nbsp; cm_about &nbsp; &nbsp; &nbsp;= 101; { ...these later &nbsp; &nbsp;}<br> <br><br>&nbsp; &nbsp; 这个实际的窗口处理过程也是相当普通。几个窗口消息(如wm_nccreate)必须处理。然而,对我们来说,更重要的事情是处理wm_mycallback和wm_command消息: <br><br>function wndproc (window : hwnd; msg, wparam, lparam : integer): integer; stdcall;<br>begin<br>&nbsp; result := 0;<br>&nbsp; case msg of<br>&nbsp; &nbsp; wm_nccreate &nbsp; : result := 1;<br>&nbsp; &nbsp; wm_destroy &nbsp; &nbsp;: postquitmessage(0);<br>&nbsp; &nbsp; wm_command &nbsp; &nbsp;: begin { a command was chosen from the popup menu }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (wparam = cm_exit) then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; postmessage(window,wm_destroy,0,0)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if (wparam = cm_about) then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; messagebox(0,'shell test copyright ?'+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;'jani j鋜vinen 1996.',<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;'about shell test',mb_ok)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else opendesktopicon(wparam-cm_about);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; wm_mycallback : begin { our icon was clicked }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (lparam = wm_lbuttondown) then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showiconpopupmenu<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if (lparam = wm_rbuttondown) then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showaboutpopupmenu;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; else result := defwindowproc(window,msg,wparam,lparam);<br>&nbsp; end;<br>end;<br> <br><br>&nbsp; &nbsp; 就象你看到的一样,当用户单击图标时,windows提示我们。注意我们不使用通常使用的wm_lbuttondown 消息,而使用wm_mycallback message,详细的消息信息存储在lparam参数中。 <br><br>&nbsp; &nbsp; 当用户单击鼠标右键,我们创建一个菜单在桌面上。 <br><br>type<br>&nbsp; ticondata = array[1..100] of string;<br>var<br>&nbsp; icondata &nbsp; : ticondata;<br>procedure showiconpopupmenu;<br>var<br>&nbsp; shellfolder : ishellfolder;<br>&nbsp; enumidlist &nbsp;: ienumidlist;<br>&nbsp; result &nbsp; &nbsp; &nbsp;: hresult;<br>&nbsp; dummy &nbsp; &nbsp; &nbsp; : ulong;<br>&nbsp; itemidlist &nbsp;: titemidlist;<br>&nbsp; pntr &nbsp; &nbsp; &nbsp; &nbsp;: pitemidlist;<br>&nbsp; strret &nbsp; &nbsp; &nbsp;: tstrret;<br>&nbsp; popupmenu &nbsp; : hmenu;<br>&nbsp; itemid &nbsp; &nbsp; &nbsp;: integer;<br>&nbsp; pos &nbsp; &nbsp; &nbsp; &nbsp; : tpoint;<br>&nbsp; procedure addtomenu(item : string);<br>&nbsp; var s : string;<br>&nbsp; begin<br>&nbsp; &nbsp; icondata[itemid-cm_about] := item;<br>&nbsp; &nbsp; s := extractfilename(item);<br>&nbsp; &nbsp; if (system.pos('.',s) &lt;&gt; 0) then setlength(s,system.pos('.',s)-1);<br>&nbsp; &nbsp; appendmenu(popupmenu,mf_enabled or mf_string,itemid,pchar(s));<br>&nbsp; &nbsp; inc(itemid);<br>&nbsp; end;<br>begin<br>&nbsp; popupmenu := createpopupmenu;<br>&nbsp; itemid := cm_about+1;<br>&nbsp; shgetdesktopfolder(shellfolder);<br>&nbsp; shellfolder.enumobjects(mainwindow,shcontf_nonfolders,enumidlist);<br>&nbsp; pntr := @itemidlist;<br>&nbsp; result := enumidlist.next(1,pntr,dummy);<br>&nbsp; while (result = noerror) do begin<br>&nbsp; &nbsp; shellfolder.getdisplaynameof(pntr,shgdn_forparsing,@strret);<br>&nbsp; &nbsp; with strret do addtomenu(string(cstr));<br>&nbsp; &nbsp; result := enumidlist.next(1,pntr,dummy);<br>&nbsp; end;<br>&nbsp; enumidlist.release;<br>&nbsp; shellfolder.release;<br>&nbsp; getcursorpos(pos);<br>&nbsp; appendmenu(popupmenu,mf_separator,0,'');<br>&nbsp; appendmenu(popupmenu,mf_enabled or mf_string,cm_exit,'e&amp;xit');<br>&nbsp; setforegroundwindow(mainwindow);<br>&nbsp; trackpopupmenu(popupmenu,tpm_leftalign or tpm_leftbutton,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pos.x,pos.y,0,mainwindow,nil);<br>&nbsp; destroymenu(popupmenu);<br>end;<br> <br><br>&nbsp; &nbsp; 上面的程序看起来有点复杂,你可以将它分成两个部分来看:创建和显示菜单。 <br><br>&nbsp; &nbsp; 列举创建菜单是用windows的外壳接口完成的。首先,我们使用shgetdesktopforlder函数得到使用桌面的ishellfolder接口。使用这个接口,我们能得到另一个接口的实例:ienumidlist。这个接口通常实现实际的列举工作。我们简单的重复调用这个函数直到错误值返回(例如:所有的菜单被列举)。当我们得到一个菜单,我们使用addtomenu函数加它。 <br><br>&nbsp; &nbsp; 当所有的菜单被列举和创建后,现在我们需要运行这个菜单。我们将找到的菜单保存到一个全局的list变量中,每一个菜单都拥有它的菜单号。这确保我们能得到它的索引。 <br><br>&nbsp; &nbsp; &nbsp; opendesktopicon(wparam-cm_about) <br><br>当然,wparam中储存了用户单击鼠标的菜单的菜单号(id)。 <br><br>&nbsp; &nbsp; 下面我们将处理运行用户选择的菜单。 <br><br>procedure opendesktopicon(number : integer);<br>var<br>&nbsp; s : string;<br>&nbsp; i : integer;<br>begin<br>&nbsp; s := icondata[number];<br>&nbsp; i := shellexecute(0,nil,pchar(s),nil,nil,sw_shownormal);<br>&nbsp; if (i &lt; 32) then begin<br>&nbsp; &nbsp; s := 'could not open selected item "'+s+'". '+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;'result was: '+inttostr(i)+'.';<br>&nbsp; &nbsp; messagebox(0,pchar(s),'shell test',mb_ok);<br>&nbsp; end;<br>end;<br> <br><br>&nbsp; &nbsp; 上面,win 32 api函数shellexecute做了所有的工作。 <br><br>&nbsp; &nbsp; 现在你应该能用delphi创建简单的任务栏的程序了。 <br>
 
多人接受答案了。
 
后退
顶部