Thema: C++ Translate 2 Delphi?

Einzelnen Beitrag anzeigen

Razor
(Gast)

n/a Beiträge
 
#1

Translate 2 Delphi?

  Alt 2. Feb 2009, 19:27
So far i've done this so far but i need help becouse i don't that much c++.

Delphi-Quellcode:
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm3 = class(TForm)
    Button1: TButton;
  Procedure findtray;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form3: TForm3;
  hwndparent,hwndtray,hwndpager,hwndtoolbar:hwnd;
implementation

function trayiconcount:integer;
var
TB_BUTTONCOUNT:integer;
begin
TB_BUTTONCOUNT:=$418;
result:=sendmessage(hwndtoolbar,tb_buttoncount,0,0);
end;

{$R *.dfm}
procedure TForm3.Button1Click(Sender: TObject);
begin
findtray;
form3.caption:=inttostr(trayiconcount);
end;

Procedure Tform3.findtray;
begin
hwndparent:=findwindow('shell_traywnd',nil);
hwndtray:=findwindowex(hwndparent,0,'traynotifywnd',nil);
hwndpager:=findwindowex(hwndtray,0,'syspager',nil);
hwndtoolbar:=findwindowex(hwndpager,0,'toolbarwindow32',nil);
end;

function trayicondata:integer;
var

hprocess,explorerpid, bytes,length:integer;
pexplorerpid,pbyte,pbutt :^integer;
begin
pexplorerpid:=nil;
explorerpid:=0;


bytes:=4096;
pbyte:=@bytes;


pbutt:=windows.VirtualAllocEx(hprocess,pbyte,4096,4096,4);
 windows.GetWindowThreadProcessId(hwndtoolbar,pexplorerpid ) ;
 result:=windows.OpenProcess(2035711,false,explorerpid);

 if hprocess=0 then





end;


end.



Zitat:
Working with the System Tray in .Net
Introduction
Since I released the last version of the Sidebar (admittedly some time ago), Iʼve had a lot
of PMs and emails asking how exactly you communicate with the System Tray
through .Net. The answer is that itʼs not easy. Unless youʼre very confident in .Net, you
should probably turn away. We need to deal with variables in other processes memory
spaces, and most of it is done in unsafe code.
Note: This article is written with C# code examples only
Step One: Find the System Tray
The first thing we need to do in order to interact with the tray is find itʼs hWnd.
This method uses the native FindWindow function to locate first the whole Taskbar. Then
the FindWindowEx function is used to go down the tree of child windows, until we find the
hWnd of the tray, which is a window of class ToolbarWindow32. Both FindWindow and
FindWindowEx are found in the user32.dll library.
One important detail of this code is that we find windows by using their class names and
parent windows only. This allows the code to work on machines with different languages.
As a result of this method, we have the hWnd of the tray, which is just a ToolbarWindow32
underneath. We can exploit this to access information about the buttons it contains.
Code:
private IntPtr FindTray()
{
IntPtr hwndParent = NativeMethods.FindWindow("Shell_TrayWnd", null);
IntPtr hwndTray = NativeMethods.FindWindowEx(hwndParent, IntPtr.Zero,
"TrayNotifyWnd", null);
IntPtr hwndPager = NativeMethods.FindWindowEx(hwndTray, IntPtr.Zero, "SysPager",
null);
hwndParent = NativeMethods.FindWindowEx(hwndPager, IntPtr.Zero,
"ToolbarWindow32", null);
return hwndParent;
}
Working with the System Tray in .Net
© Karl Wagner, 2008
Page 1 of 7
Step Two: Count the number of tray items
As I mentioned earlier, the system tray is just a standard ToolbarWindow32. We can
demonstrate this, by having our program count the number of items in the tray.
The ToolbarWindow32 responds to the TB_BUTTONCOUNT message, so all we have to
do is send that message to the hWnd to count the number of items in the tray.
This method simply sends the button count message to the system tray. Note that the
number returned will probably be different from what you see, because many applications
run with invisible icons, especially those with animated tray icons (more on those later).
Step Three: Get the button information
This is where things start to get complicated. We can count the number of buttons in the
system tray easily, because that gives a result through the messaging system. Getting
detailed information back from messages requires a bit more work.
There are 2 structures and a String that we need to populate with information for each
button: a TRAYDATA and TBBUTTON structure, and a String.
• The TRAYDATA and TBBUTTON give us information about the button itself
• And weʼll use the String to store its ToolTip text
For convenience, I group these members together in the TrayIconData class
Note: The definitions for these structures are provided in the Appendix for convenience
Code:
private unsafe TrayIconData[] getButtons()
{
byte[] buffer = new byte[4096];
TrayIconData[] data = new TrayIconData[1];
//Find Explorer’s PID
uint ExplorerPID = 0;
NativeMethods.GetWindowThreadProcessId(_systray, out
ExplorerPID);
//Hence get an hProcess
IntPtr hProcess = NativeMethods.OpenProcess(2035711, false,
ExplorerPID);
In this first part of the method, we declare its signature (note that the method is unsafe -
we use coding practices that .Net does not typically allow. Make sure you allow unsafe
code in your project).
private int GetTrayIconCount()
{
uint TB_BUTTONCOUNT = 0x418;
int iconCount = (int)NativeMethods.SendMessage(_systray,
TB_BUTTONCOUNT,
IntPtr.Zero,
IntPtr.Zero);
return iconCount;
}
Working with the System Tray in .Net
© Karl Wagner, 2008
Page 2 of 7
We then use the system trayʼs hWnd to find the Process ID (PID) of its process, which is
explorer.exe. From explorerʼs PID, we can obtain a handle to the process through the
OpenProcess method.
[pre]if (hProcess != IntPtr.Zero)
{
//Allocate some memory for the button data
IntPtr butt = NativeMethods.VirtualAllocEx(hProcess, IntPtr.Zero, new
UIntPtr(4096), 4096, 4);
int length = this.TrayItemCount;
data = new TrayIconData[length];
for (int id = 0; id < length; id++)
{
data[id] = new TrayIconData();
fixed (TBBUTTON* tbbuttonRef = &data[id].button)
{
IntPtr lpBuffer = new IntPtr((void*)tbbuttonRef);
//Get the button data for the id&#8208;th button, let it get
written to the memory we allocated
NativeMethods.SendMessage(_systray, 1047, new IntPtr(id),
butt);
int num = 0;
IntPtr lpNumberOfBytesRead = new IntPtr((void*)&num);
//Read the data back in to our TBBUTTON structure
if (NativeMethods.ReadProcessMemory(hProcess, butt, lpBuffer,
new UIntPtr((uint)sizeof(TBBUTTON)), lpNumberOfBytesRead))
[/pre]
With this section of the method, we first check if the hProcess for explorer that we obtained
before is valid. If it is, we use the VirtualAllocEx method to allocate some memory in
explorer&#700;s context. Since we are using .Net, we need to create our structures in explorer&#700;s
memory space, call the methods to retrieve button information, having the results stored
where we allocated before, and then read the results out.
So after we have allocated some memory in explorer&#700;s space, we create an array of
TrayIconData classes for each button in the system tray (using the counting method from
Step Two). Then, we use the fixed statement to stop the Garbage Collector moving the
class we are working on, and create a pointer to the TBBUTTON member of the class (this
is were we need unsafe code).
Once we have the pointer, we ask the system tray to populate the TBBUTTON structure
we allocated in explorer&#700;s space, and then read that memory back in to the TBBUTTON
structure that we fixed in our own space.
Working with the System Tray in .Net
© Karl Wagner, 2008
Page 3 of 7
{
//Create a fixed TRAYDATA structure
fixed (TRAYDATA* traydataRef = &data[id].traydata)
{
IntPtr ptr5 = new IntPtr((void*)traydataRef);
//Read the value back in to our TRAYDATA structure
NativeMethods.ReadProcessMemory(hProcess, new
IntPtr(data[id].button.dwData), ptr5, new UIntPtr((uint)sizeof(TRAYDATA)),
lpNumberOfBytesRead);
}
The dwData member of the TBBUTTON structure gives us a pointer to the TRAYDATA
structure for the button. However, we copied this from explorerʼs memory space, so that
pointer points to a location in explorerʼs space. To retrieve the TRAYDATA structure from
explorerʼs space, we use the ReadProcessMemory function, as we did for the
TBBUTTON.
Code:
fixed (byte* numRef = buffer)
{
//Get the button's text in to the allocated memory
int len = (int)NativeMethods.SendMessage(_systray,
1099, (IntPtr)data[id].button.idCommand, butt);
if (len != &#8208;1)
{
//And read it back, putting it in the text object
IntPtr ptr6 = new IntPtr((void*)numRef);
if (NativeMethods.ReadProcessMemory(hProcess, butt,
ptr6, new UIntPtr(4096), lpNumberOfBytesRead))
data[id].Text = Marshal.PtrToStringAuto(ptr6, len);
else
data[id].Text = "";
}
else
data[id].Text = "";
}
}
}
}
    NativeMethods.VirtualFreeEx(hProcess, butt, UIntPtr.Zero, 32768);
}
    return data;
}
In this final section of the method, we create a buffer for the string giving us the buttonʼs
text. In much the same way as we have done before, we send the tray a message put the
buttonʼs text in to explorerʼs memory space, and read it out. We end the method by calling
the VirtualFreeEx method to free the memory that we allocated in explorerʼs space, and
returning the array of TrayIconData classes - each class containing the information we
need to reconstruct the button it represents.
Working with the System Tray in .Net
© Karl Wagner, 2008
Page 4 of 7
Step Four: Get the buttonʼs icon
Retrieving the icon for a button is a simple procedure. However, you should be aware of
the state of each button before retrieving its icon. The system tray has many invisible icons
- some for applications, some for animation purposes (each frame gets a new icon, and
one is visible at any time). Obviously we donʼt want these to be shown.
To check for invisibility, check the fsState member of the TBBUTTON structure. If it equals
8, the button is hidden and should not be displayed.
Code:
private ImageSource makeImageSource(TrayIconData ButtonData)
{
ImageSource img =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(ButtonData.traydata.hIcon,
Int32Rect.Empty, null).Clone();
DestroyIcon(ButtonData.traydata.hIcon);
return img;
}
This method creates an ImageSource from the hIcon of a button. This image source can
then be applied to any WPF object that supports it, and we will have recreated the icon.
We return a clone of the source that is created from the hIcon, as the original is destroyed
to avoid leaving open handles to the original icon.
It is worth noting that some applications (such as Windows Live Messenger) use a nonstandard
icon format that is not supported by this method. There does not seem to be any
documentation on this icon format.
Step Five: Interact with the button
Simply having an icon is not enough to duplicate the system tray - we need some type of
interaction with the buttons. We have already seen how to retrieve the tooltip text. Now we
will see how to send events to the buttons.
What happens is that we use event handlers for our icon to emulate clicking the real tray
icon. We use the messaging system to send the tray button the click event. Most tray
buttons will launch a standard system context menu, which is placed wherever the mouse
is when the system gets the command to show it. Hence when the user clicks our button,
the menu appears to have been created from our button, but it has actually been created
by the real tray button.
Code:
void SysTrayIconView_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
PostMessage(ButtonData.traydata.hwnd, ButtonData.traydata.uCallbackMessage,
(int)ButtonData.traydata.uID, 0x201);
IntPtr ptr = SetForegroundWindow(ButtonData.traydata.hwnd);
e.Handled = true;
}
This event handler uses the PostMessage method to send the left button down event to
the button specified by the ButtonData member.
Working with the System Tray in .Net
© Karl Wagner, 2008
Page 5 of 7
For each event, there is a different message to send
Event Message
Left Button Down 0x201
Left Button Up 0x202
Right Button Down 0x204
Right Button Up 0x205
Final Thoughts
This guide has shown you how to interact with the system tray from a .Net application.
There are likely more efficient ways to do it, but this method works perfectly well. However,
due to the nature of .Net, we are not informed of when changes to the tray occur. What we
have are interactive yet not dynamic screenshots of the information represented by the
tray. To receive updates, we would have to use some form of code injection to hook
messages received and sent by the tray to determine when the data is changing.
This should be enough to get you started with working with the system tray. Happy
hacking!
Karl
Working with the System Tray in .Net
© Karl Wagner, 2008
Page 6 of 7
Appendix: Structure Definitions
Code:
[StructLayout(LayoutKind.Sequential)]
public struct TRAYDATA
{
public IntPtr hwnd;
public uint uID;
public uint uCallbackMessage;
private uint Reserved;
private uint Reserved2;
public IntPtr hIcon;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TBBUTTON
{
public int iBitmap;
public int idCommand;
public byte fsState;
public byte fsStyle;
public byte bReserved0;
public byte bReserved1;
public int dwData;
public int iString;
}
public class TrayIconData
{
public TrayIconData()
{
button = new TBBUTTON();
traydata = new TRAYDATA();
Text = " ";
}
public TBBUTTON button;
public TRAYDATA traydata;
public string Text;
}
Working with the System Tray in .Net
© Karl Wagner, 2008
Page 7 of 7
[edit=mkinzler]C-Tags eingefügt Mfg, mkinzler[/edit]
  Mit Zitat antworten Zitat