|
Oh, and don't forget to set the CharSet field on the StructLayoutAttribute as well.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
ok, now I get an return code of 0, which I'm assuming is the NErr_Success code, with the following code.
[DllImport("NetApi32.dll",CharSet=CharSet.Unicode)] private static extern int NetUseGetInfo(string SrvrName,string MappedDrive,int Level,ref structUSE_INFO_2 MapInfo);
[DllImport("NetApi32.dll",CharSet=CharSet.Unicode)] private static extern int NetApiBufferFree(ref structUSE_INFO_2 MapInfo);
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
private struct structUSE_INFO_2
{
public string sLocal;
public string sRemote;
public string sPassword;
public int iType;
public int iRefCount;
public int iUseCount;
public string sUsername;
public string sDomain;
}
...
...
...
structUSE_INFO_2 MappInfo = new structUSE_INFO_2();
int Err=NetUseGetInfo(null,DriveLetter,2,ref MappInfo);
Username=MappInfo.sUsername;
Err=NetApiBufferFree(ref MappInfo);
However the when I interrogate the structUSE_INFO_2 structure, all the memebers are null . Do I need to set any of the USE_INFO_2 members to a value first ? I didn't see any documentation on it.
|
|
|
|
|
Because the last param is NetUseGetInfo is LPBYTE* , which is a typedef for unsigned char ** . If it was just LPBYTE , your little shortcut of using ref structUSE_INFO_2 would work.
Instead, you have to pass an IntPtr (by the way, it should just be an out param, not a ref , though it doesn't hurt in this case) then use Marshal.PtrToStructure like so:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
internal class GetInfo
{
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.Error.WriteLine("You must specify a drive letter.");
Environment.Exit(1);
}
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
Console.Error.WriteLine("Supported only on Windows NT.");
Environment.Exit(2);
}
IntPtr ptr = IntPtr.Zero;
if (0 == NetUseGetInfo(null, args[0], 2, out ptr))
{
UseInfo2 info = (UseInfo2)Marshal.PtrToStructure(ptr,
typeof(UseInfo2));
Console.WriteLine("Username: " + info.username);
Console.WriteLine("Domain: " + info.domainname);
NetApiBufferFree(ptr);
}
else
{
int error = Marshal.GetLastWin32Error();
Console.Error.WriteLine("Error " + error);
Environment.Exit(error);
}
}
[DllImport("netapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern uint NetUseGetInfo
(
string server,
string drive,
uint level,
out IntPtr info
);
[DllImport("netapi32.dll")]
public static extern uint NetApiBufferFree(IntPtr ptr);
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
internal struct UseInfo2
{
public string local;
public string remote;
public string password;
public uint status;
public uint type;
public uint refcount;
public uint usecount;
public string username;
public string domainname;
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Awesome, thanks again Heath....
|
|
|
|
|
i want to write my own listview control that i can repaint the columnhead's color.
but i dont know how to do it.
i use Graphics.FillRectangle() in the OnPaint() method but did not get the correct result.
|
|
|
|
|
The ListView class encapsulates the List-View common control. Sticking to pure managed code won't accomplish what you need. You must extend the ListView control, override WndProc , and handle windows messages like you would in VC++.
There are plenty of articles here on CodeProject about this, and you should familiarize yourself with the windows messages and common controls by reading Windows Controls[^].
For one example, see a previous post about defining an event to fire when column widths change: http://www.codeproject.com/script/comments/forums.asp?msg=807702&forumid=1649#xx807702xx[^].
Another good article about handling notification messages for the List-View common control (because that's really what this all comes down to) is http://www.codeproject.com/cs/miscctrl/listviewfilter.asp[^].
In your case, since you're paining, you'll need to handle the NM_CUSTOMDRAW message (for a list-view). This will, once you've handle the right sequence of windows messages, give you an HDC (handle to a device context). You can get a Graphics object from this by using Graphics.FromHdc , but simply overriding the OnPaint method (or handlig the Paint event, which is much slower and a bad idea when done in a derived control) will not work. You must draw to the DC that the list-view is using for the list-view column header.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I want to know that wich form is running now in my project at design time.
and then, know properties and field that each form have(at runtime).
|
|
|
|
|
Use reflection. Read Discovering Type Information at Runtime[^] in the .NET Framework SDK.
You can also use the ComponentModel to discover type information in a more design-time friendly way. Read about the TypeDescriptor and it's members in the .NET Framework sDK as well.
As far as which form is "running", that's entirely up to your implementation, especially since I have no idea of what you're talking about.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I'm curious to know and I hope none of you get the wrong idea. I was just wondering if this is possible it doesn't matter if its yahoo or whatever. I just use yahoo as an example. If the window is open and you see your friends names in say billy,bob,sam. Instead of taking and doing a hi pm to each and every one of them. Is there a way in c# to read the names from the other control (yahoo window) and then let you pm then all at one time? If that is too much is there a way to read text from another window into c#? If i have word open would there be a way to tell it read what is on that screen into the text box on my windows form. Just curious.
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
You would probably need to use Spy++ to capture the handle of each sub-window (input textbox) for each IM window you have open. After that you would need to have your application perform a SendMessage with a WM_SETTEXT message included to apply the text you want each window to have. Make sense?
- Nick Parker My Blog | My Articles
|
|
|
|
|
Yeah i see what your talking about much like is done in c++. The thing is and maybe you can shed some light on the subject. How exactly do you use spy++? I'm kinda new to the programming field so I ask out of lack of knowledge. My understanding with spy is it gives me the (handle if you will) the hex or dword value of the control? I tried running it before but was lost. Is there any kinda free documentation other than the sdk and msdn. I don't mind reading those but sometimes they are too far advanced and I just shake my head and go whatever. Thanks for your information. And also i assume that if i wanted to read in the data from the control it would be ReceiveMessage?
thanks again
Nick Parker wrote:
You would probably need to use Spy++ to capture the handle of each sub-window (input textbox) for each IM window you have open. After that you would need to have your application perform a SendMessage with a WM_SETTEXT message included to apply the text you want each window to have. Make sense?
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
Open it up and try it. It's a simple-to-use window style and message viewer. It's in your Start menu, under the program group for Visual Studio (whatever version)-<Tools (or something similar).
Just try it out - it's not a difficult program, and there's always the Help menu. It's how we learned.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
You can do this programmatically at runtime, too, instead of using Spy++ as Nick said. You have to P/Invoke FindWindow and/or FindWindowEx , which you can search for windows using their title or class name (better using the class name since it'll never change).
Using this, you can keep calling FindWindow(Ex) using the previous found window as the parent until you get to your child (since the screen name may be in an edit control which may be in a list-box control, which may be hosted in a dialog, etc.), and then call WM_GETTEXT to get their screen name.
There's no truly generic way of doing, this, though. What Nick and I mentioned would be the closest thing to generic as possible, since you could design your recursive window finding algorithm to use heuristics to find screen names; when it does, it knows it's found the right window (that contains the screen names).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
First and formost thank you as always for your help. Nick thank you as well. I like how you give me an idea and force me to run with it. In any case I have a question.
I like your method of using the FindWindow apposed to having to search in spy++ every time. I somewhat have It working but here is the deal. I have the following.
I have a little application that comes up to enter the class name and enter the window name. Here is where I run into the problem. I can see in spy++ that I have say for notepad for instance. I have classname NotePad and then a subwindow class named Edit. I have something like this
public class Win32
{
public const uint WM_SETTEXT = 0x000C;
[DllImport("user32.dll")]
public static extern int FindWindow(
string lpClassName,
string lpWindowName
);
[DllImport("user32.dll")]
public static extern long SendMessage(
int hWnd,
uint msg,
uint wparam,
string text
);
then i have in my form a button event as follows
private void button1_Click(object sender, System.EventArgs e)
{
int i=Win32.FindWindow(txtClsNm.Text ,txtWndNm.Text);
Win32.SendMessage(i,Win32.WM_SETTEXT,0,"Testing my program");
}
The trouble I'm having is this. As you stated I could call FindWindow using the previous window as the parent. I kinda see what your talking about My question though is how do I let the function know? Example, if Edit Class is a sub of NotePad what do I call in order for it to address Edit?
I tried passing with the textbox for the class name NotePad Edit but that doesn't seem to work. So basically I'm asking kick me in the arse and let me buy a clue
If I Call NotePad and then the Window Name of Untitled The title bar changes to Testing my program so I know I'm at least on the the right track. Thanks again Hope to not be too much of a pest in my learning days
Win32newb
"Don't Laugh, I can't help it I was born this way "
|
|
|
|
|
If FindWindows returns 0 it couldn't find it....
/\ |_ E X E GG
|
|
|
|
|
This code is soo horibile, but it works. I'm not sure if you got it to work, but this does.... I keep spacing out when I was reading, oh well good practice for me...
public const int WM_SETTEXT = 0x000C;
[DllImport("user32.dll")]
static extern int FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern int FindWindowEx(int hwndParent, int hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
static extern int SendMessage(int hWnd, int Msg, int wParam, string lParam);
int ParenthWnd;
int hWnd;
private void button1_Click(object sender, System.EventArgs e)
{
string lpszParentClass = "Notepad";
string lpszParentWindow = "Untitled - Notepad";
string lpszClass = "Edit";
ParenthWnd = FindWindow(lpszParentClass, lpszParentWindow);
if (ParenthWnd==0)
Console.WriteLine("Notepad Not Running");
else
{
hWnd = FindWindowEx(ParenthWnd,hWnd,lpszClass,"");
if (hWnd.Equals(IntPtr.Zero))
Console.WriteLine("What the F??? Notepad doesn't have an edit component ?");
else
{
MessageBox.Show("Notepad Window: " + ParenthWnd.ToString());
MessageBox.Show("Edit Control: " + hWnd.ToString());
string hi="hello";
SendMessage(hWnd, WM_SETTEXT, hi.Length, hi);
}
}
}
/\ |_ E X E GG
|
|
|
|
|
eggie5 wrote:
hWnd = FindWindowEx(ParenthWnd,hWnd,lpszClass,"");
This is what I was trying to figure out and thanks. Just trying to learn this stuff. I know I crazy questions just I lack the experience that others on here have but one day I'll be able to to run with the big dogs. But by the then they will have newer toys haha. Will I ever win
Thanks again.
tony
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
Here's a better explinaion of the method...
The FindWindowEx function retrieves the handle to a window whose class name and window name match the specified strings. The function searches child windows, beginning with the one following the given child window.
If the function succeeds, the return value is the handle to the window that has the specified class and window names.
PARAMETERS
· hwndParent
Identifies the parent window whose child windows are to be searched.
If hwndParent is NULL, the function uses the desktop window as the parent window. The function searches among windows that are child windows of the desktop.
· hwndChildAfter
Identifies a child window. The search begins with the next child window in the Z order. hwndChildAfter must be a direct child window of hwndParent, not just a descendant window.
If hwndChildAfter is NULL, the search begins with the first child window of hwndParent.
Note that if both hwndParent and hwndChildAfter are NULL, the function searches all top-level windows.
· lpszClass
Points to a null-terminated string that specifies the class name or is an atom that identifies the class-name string. If this parameter is an atom, it must be a global atom created by a previous call to the GlobalAddAtom function. The atom, a 16-bit value, must be placed in the low-order word of lpszClass; the high-order word must be zero.
· lpszWindow
Points to a null-terminated string that specifies the window name (the window’s title). If this parameter is NULL, all window names match.
I don't know how much sense that makes to you but.... I dont' really know either.
/\ |_ E X E GG
|
|
|
|
|
You need to P/Invoke FindWindowEx in order to specify the parent from which searching begins.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Yeah, thanks I figured it out after i posted. I go duh wait a minute he said FindWindowEx in his post as well so I did like a good little newbie and looked it up. Then eggie posted and my code is almost identical so I'm on the right track just headed the wrong way
Anway, as always thanks again. If you are a father enjoy fathers day. If your not hope you enjoy with your father.
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
I think WM_GETTEXT only returns the length of the text. Uh, is this what you meant?
Nevermind, it's just really complicated...
/\ |_ E X E GG
|
|
|
|
|
Well, you are right it is complicated. However, i just take one step and time and when I figure it out and understand it I can look back laugh and go man i made this harder than it really was and wow this stuff is cool I don't know I just always wanted to know how programs controlled other programs because i remember long time back in 95 I would use I think it was macro recorder or something like that would generate task for me. Now with the help of you and others, I see where I can do this automation but in a better way. Like I use this program called Total Recorder don't know have heard of it but it lets you record streaming audio. Anway, there is a radio show that comes on called Art Bell (Coast to Coast) and most of the time I'm a sleep so I have to get up and turn the recorder on then go back to bed. Now all I will have to do is find the message handlers and pass them the wm_control command and few other things and it will do all this automatically for me by simply setting a timer in the program. And I can get one of those timers that turn the electricity on and off to my stereo. Ha sorry for the ramble just see this as fun.
Thanks again.
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
Hey, I have a working sample of reading some text using the SendMessage and WM_GETTEXT . Check it out...
Add this to your class...
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
[Out] StringBuilder lParam);
This was just on a a form with one button and a text box for the handle, here is the button click code. All it does is take the hex handler spy++ gives you and converts it to dec for the method. It removes the extea '0's at the beginning also.
private void button1_Click(object sender, System.EventArgs e)
{
char [] arr = {'0'};
string handle=this.textBox1.Text;
handle=this.textBox1.Text.TrimStart(arr);
IntPtr hWnd = new IntPtr(Convert.ToInt32(handle, 16));
MessageBox.Show(GetWindowText(hWnd));
}
Here is the method, pretty simple...
public static String GetWindowText(IntPtr hWnd)
{
IntPtr txtLength;
IntPtr retValue;
IntPtr zeroVal = new IntPtr(0);
retValue = SendMessage(hWnd,WM_GETTEXTLENGTH,zeroVal,zeroVal);
txtLength = retValue;
StringBuilder sb = new StringBuilder(txtLength.ToInt32() + 2);
retValue = SendMessage(hWnd, WM_GETTEXT, txtLength, sb);
return sb.ToString();
}
Just start spy++ and click file then find window, and then drag that little cross hair thingy over something... like ie's address bar. Then spy++ gives you the hex handle. Just paste that into the text box on the fort and the message box will show the text...
Do you know about pinvoke.net[^]? That site helped me alot alot.
/\ |_ E X E GG
|
|
|
|
|
I was looking at your code and not really understanding this part. Why are you using zeroVal when its a IntPtr instead of a StringBuilder? It gives an error in the compiler as well.
c:\test\notepad writer\Form1.cs(183): Argument '4': cannot convert from 'System.IntPtr' to 'System.Text.StringBuilder'
it is in reference to:
Thanks again.
Win32newb
"Programming is like sex, make one mistake and you have to support it for a long time"
|
|
|
|
|
That will do it. Thanks to pinvoke.net.
public static String GetWindowText(IntPtr hWnd)
{
IntPtr txtLength;
IntPtr retValue;
IntPtr zeroVal = new IntPtr(0);
retValue = SendMessage(hWnd,WM_GETTEXTLENGTH,zeroVal,zeroVal);
txtLength = retValue;
StringBuilder sb = new StringBuilder(txtLength.ToInt32() + 2);
retValue = SendMessage(hWnd, WM_GETTEXT, txtLength, sb);
return sb.ToString();
}
/\ |_ E X E GG
|
|
|
|
|