Interop question

M

michelqa

When executing some win32 messages in c# I get unexpected results.
The following example is suppose to return the handle of an image in a
button control of another application but it return a negative
handle...is anybody know why it return an invalid handle like
"-989523277" ??

IntPtr ImageHandle =
Win32.SendMessage(Handle,BM_GETIMAGE,IntPtr.Zero,IntPtr.Zero);
MessageBox.Show(ImageHandle.ToString());

Note : the third param is set to IMAGE_BITMAP (0); it return 0 if
the button contain no image.

Thanks...
 
M

michelqa

Can you be more specific?  Why do you believe the value "-989523277" tobe  
an invalid handle value?  Have you actually tried to use it as an HBITMAP  
and had that fail?  Can you show a concise-but-complete code sample that  
reliably demonstrates whatever problem you're actually having?

Pete

I suppose it's invalid since it's negative and since i'm not able to
recreate the bitmap in my application...it return a "Generic
exception"

//Handle = button handle of another application
IntPtr ImageHandle =
Win32.SendMessage(Handle,BM_GETIMAGE,IntPtr.Zero,IntPtr.Zero);
MessageBox.Show(ImageHandle.ToString());
System.Drawing.Bitmap Bitmap =
System.Drawing.Bitmap.FromHbitmap(ImageHandle); //generic exception
from gdi..invalid handle?
// Just want to get a usable bitmap here
 
M

michelqa

Ok , I'll try to explain the problem :
1- I know that WM_GETIMAGE is suppose to return an hImage hex
c50512b3 (3305444019) ... I know that because I'm logging the message
in SPY++
2- My sendMessage in my c# app return -989523277 (or
8975925797277995699 when modifying sendmessage definition to return a
long instead of a IntPtr) *** Why this difference???? ****
3- Even with the correct image handle hardcoded like this :
System.Drawing.Image MyImg=
System.Drawing.Image.FromHbitmap((IntPtr)3305444019);
I get the error : Arithmetic operation resulted in an overflow.

As I understand it FromHbitmap want an IntPtr and 3305444019 is to big
for a Integer

Dont think a more complete example will help to understand the problem
but here is my example...I have a Win32 application and I want to copy
Button image from it and put the image in a button or a picturebox in
my c#

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr
wparam, IntPtr lparam);
int BM_GETIMAGE = 0x00F6;
IntPtr ImageHandle =
SendMessage(Handle,BM_GETIMAGE,IntPtr.Zero,IntPtr.Zero);
MessageBox.Show(ImageHandle.ToString());
System.Drawing.Image MyImg=
System.Drawing.Image.FromHbitmap((IntPtr)3305444019); //Arithmetic
operation resulted in an overflow.
//System.Drawing.Image MyImg=
System.Drawing.Image.FromHbitmap(ImageHandle); //Exception
Button Button1 = new Button();
Button1.Image=MyImg;
 
M

michelqa

Just to make things correctly :

1- Download controlSpy from
http://www.microsoft.com/downloads/...4d-0531-4ec2-8b27-2e463b315f16&displaylang=en
2- Run controlSpy6.exe. Go to the button section, Apply the BS_BITMAP
style, and then go to the Message tab and send the "SetImage" message.
3- With Spy++ get the handle of the button and convert it to integer
4- Replace the Handle value in for the Handle variable in the
Form_load of the following code
5- Run the code. (My code is .net 1.0)
<Code>
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Data;

namespace GetWin32ButtonImage
{
public class Form1 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code

private void InitializeComponent()
{

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);

}
#endregion

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hwnd, int msg,
IntPtr
wparam, IntPtr lparam);

[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
IntPtr Handle=(IntPtr)666666; //*** REPLACE THE HANDLE HERE ***//
int BM_GETIMAGE = 246;
IntPtr ImageHandle =
SendMessage(Handle,BM_GETIMAGE,IntPtr.Zero,IntPtr.Zero);
System.Drawing.Image MyImg=
System.Drawing.Image.FromHbitmap(ImageHandle);
MessageBox.Show("We have a valid bitmap!!! :
height="+MyImg.Height.ToString())
}
}
}
</Code>

Now we have a full working example! ;o) You can skip the 3 first step
if you can find a button with BS_BITMAP style and with an image. (not
an icon...BS_ICON)
 
S

Stephen Martin

The ImageHandle you are retrieving is relative to the button's process. In
the process in which you are trying to create the Bitmap that handle is
meaningless.
 
M

michelqa

OK thanks....that's explain the weird unusable image handle... The
*only* way to do it will be by creating and a dll to inject into the
other process and setting a windows hook. Is there any other way to
execute my code into the other process ?
 
M

michelqa

It's _possible_ that if you describe what you're really trying to do here,  
 from the high-level goal perspective, ignoring completely any particular  
implementation details, someone could offer better advice.

Pete

I'm doing a tool like spy++. Win32 controls are interpreted (runtime
converted) as .net object
for example Win32 control properties are displayed in a managed
propertyGrid of my spy++ application just like any other .Net
control.

My question was about filling Button.Image in my property grid
(selectedObject is a button) when converting a Win32 control to a .net
control.

I was just wondering why WM_GETIMAGE return unusable image handle...
(never seen a negative handle since now) With your help I understand
that it return a negative unasable handle because it's in another
process.

I already use a dll and a windows hook to get things like
Button.ImageList with WM_GETIMAGELIST and will probably use the same
kind of code to get the image handle of WM_GETIMAGE from the other
process.

Pete : What you mean By malware-like techniques?? Is there any other
way to do this without hooking windows to inject a dll into the other
process???

Since you always trying to help me in different threads here , you now
know why i'm asking win32 to .net questions. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top