WinForms FAQ - Win32

Find answers for the most frequently asked questions
Expand All Collapse All

Yes, you can use the FormatMessage Win32 API. Sample projects for C# and VB.NET are enclosed. This is how the declaration looks like:


    [DllImport(''Kernel32.dll'')]
    public static extern int FormatMessage(int flags, IntPtr source, int messageId, int languageId, StringBuilder
      buffer, int size, IntPtr arguments );

Called like so:


// You can call FormatMessage to get a descriptive error message
        StringBuilder sbFormatMessage = new StringBuilder(1024);
        retVal = Interop.FormatMessage(Interop.FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, Marshal.GetLastWin32Error(), 0, sbFormatMessage, 
          sbFormatMessage.Capacity, IntPtr.Zero);

Download C# sample, formatmessage.zip
Download VB.NET sample, formatmessage_VB.zip

Permalink

We have two suggestions with sample projects how you host a WebBrowser control inside a form and display HTML contents and listen to events such as NavigateComplete or BeforeNavigate. Of course there are many other ways to do this.

Download htmlviewer.zip for two sample projects for the suggestions discussed below.

1) The first suggestion is to generate an ActiveX wrapper for shdocvw using the aximp tool.
The command line for this tool should be as follows:

  
  aximp c:\windows\system32\shdocvw.dll

This will generate the following assemblies.

  
  Generated Assembly: D:\Syncfusion\faq\HtmlBrowser\HtmlViewer2\SHDocVw.dll
  Generated Assembly: D:\Syncfusion\faq\HtmlBrowser\HtmlViewer2\AxSHDocVw.dll

Now you can reference these dlls in your project and use AxWebBrowser. In the attached HtmlViewer2 sample we have derived a HtmlControl class from AxWebBrowser and added some properties that let you specify a CSS Stylesheet and the Html content as a string.

2) Our second sample lets you bypass the generation of a ActiveX wrapper. You don’t have to include and ship shdocvw.dll and axshdocvw.dll. In the attached HtmlViewer sample, we derived from AxHost and attached our own IWebBrowserEvents interface by overriding the CreateSink, AttachInterfaces and DetachSink methods.

You can use HtmlControl in your form and specify HTML content by assigning a HTML string to HtmlControl. A cascading style sheet can be specified by assigning a path name to the CascadingStyleSheet property. The sample demonstrates how to use a CSS style sheet that has been embedded as a resource in the assembly.

Permalink

Please check out this article from the October 2000 issue of MSDN Magazine.

Allen Weng gives the following explanation in a post on the microsoft.public.dotnet.framework.windowsforms newgroup.

If what you are looking for is just to intercept and handle generic Windows messages such as WM_NCPAINT or alike, you can override WndProc (). You don’t need to use the hook procedure. Here is some code that does this:

public enum WinMsg 
{
	WM_KEYDOWN = 256,
	WM_KEYUP = 257,
	WM_PAINT = 15,
	WM_CREATE = 1
	.......
	.......
};

protected override void WndProc(ref System.Windows.Forms.Message m)
{
	.............. 
	if (m.Msg == (int) WinMsg.WM_PAINT)
	{
		m.Result = new IntPtr(0); // no further processing is needed.
		.......
		.......
	}
	..............
	base.WndProc(ref m);
}

But if you need to use a hook procedure, be cautious since they might interfere with normal execution of other applications. In some extreme cases, they might bring the whole system down if not processed correctly. Here is the code snippet that shows you how to do implement and use the hook procedure in .NET:

public class Win32Hook
{
	[DllImport('kernel32')]
	public static extern int GetCurrentThreadId();

	[DllImport( 'user32', CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
	public static extern int  SetWindowsHookEx( HookType idHook,
				HOOKPROC lpfn,
				int hmod,
				int dwThreadId
				);

	public enum HookType
	{
		WH_KEYBOARD = 2
	}
	public delegate int HOOKPROC(int nCode, int wParam, int lParam);

	private HOOKPROC hookProc; //private field with class scope

	public void SetHook()
	{
		 // set the keyboard hook
		hookProc = new HOOKPROC(this.MyKeyboardProc);

            		SetWindowsHookEx(HookType.WH_KEYBOARD, hookProc, 0,
GetCurrentThreadId());

	}

	public int MyKeyboardProc(int nCode, int wParam, int lParam)
	{
		return 0;
	}
}

To install the hook procedure

            Win32Hook hook = new Win32Hook();
            hook.SetHook();
Permalink

You have to get a handle to the desktop and draw on the desktop. This means that whatever you draw will not be automatically refreshed when another window is dragged over it.

	[DllImport('User32.dll')]
	public extern static System.IntPtr GetDC(System.IntPtr hWnd);

	private void button1_Click(object sender, System.EventArgs e)
	{
		System.IntPtr DesktopHandle = GetDC(System.IntPtr.Zero);
		Graphics g = System.Drawing.Graphics.FromHdc(DesktopHandle);
		g.FillRectangle(new SolidBrush(Color.Red),0,0,100,100);
	}

from a microsoft.public.dotnet.framework.windowsforms posting by Lion Shi (MS)

Permalink

Normally when you make a Form visible by setting the Visible property to true, it will show the form and set the focus too. In some cases however, you do not want it to take focus until the user clicks on it. To get this behavior, do the following utility code:

When you want to show a form without activating it:

	UtilFuncs.SetVisibleNoActivate(myForm, true); // true to show.

When you want to hide it:

	UtilFuncs.SetVisibleNoActivate(myForm, false); // false to hide.
public class UtilFuncs
{
	[DllImport('USER32.dll')]
	extern public static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags)  ;

	public const int HWND_TOPMOST = -1; // 0xffff
	public const int SWP_NOSIZE = 1; // 0x0001 
	public const int SWP_NOMOVE = 2; // 0x0002 
	public const int SWP_NOZORDER = 4; // 0x0004 
	public const int SWP_NOACTIVATE = 16; // 0x0010 
	public const int SWP_SHOWWINDOW = 64; // 0x0040 
	public const int SWP_HIDEWINDOW = 128; // 0x0080 
	public const int SWP_DRAWFRAME = 32; // 0x0020 

	public static void ShowWindowTopMost(IntPtr handle)  
	{
		SetWindowPos(handle, 
			(IntPtr)HWND_TOPMOST, 0, 0, 0, 0, 
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
	}

	public static void SetVisibleNoActivate(Control control, bool visible)
	{
		if(visible)
		{
			ShowWindowTopMost(control.Handle);
			control.Visible = true;
		}
		else
			control.Visible = false;
	}
}
Permalink

Use the DllImport attribute that is a member of the System.Runtime.InteropServices namespace. Assume your exported function found in MyDLL.dll has a signature:

	int MyFunction( LPCTSTR lpCaption, UINT uType);

The code below shows how you can access this function from within C#.

using System; 
using System.Runtime.InteropServices;

class HelloWorld 
{ 
	[DllImport('mydll.dll')] 
 	public int MyFunction(string title, int type); 
 
	public static void Main() 
 	{ 
		int nReturnValue = MyFunction('some string', 14);
  	} 
}
Permalink
	[DllImport('user32.dll', CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi)] 

	public static extern int GetMenuString(IntPtr hMenu, uint uIDItem, [MarshalAs(UnmanagedType.LPTStr)]string lpString,int maxCount,uint uFlag);

	//Usage:
	String caption = new String(’t’, 30);//using a dummy char ‘t’ here.
	int len = GetMenuString(hsysmenu, commandID, caption, 30, 0));
Permalink

Bill Zhang (Microsoft) responds to this question in a posting on microsoft.public.dotnet.frameworks.windowsforms newsgroup.

The Frameworks classes use P/Invoke to call the GetWindow API to get the HWND internally - there is no exposed way to do this. If you wish to get the Win32 HWND, here’s the code to do it, but there is no way to get a 
System.Windows.Forms.Edit control from this.


        [DllImport('user32.dll', ExactSpelling=true, CharSet=CharSet.Auto)]
        public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);

        public const int GW_CHILD = 5;

        if (combo.DropDownStyle != ComboBoxStyle.DropDownList) {
            IntPtr hwnd = GetWindow(combo.Handle, NativeMethods.GW_CHILD);
            if (hwnd != IntPtr.Zero) {
                editHandle = hwnd;
            }
        }
Permalink

To maximize the main window, you can get the handle of the main window in the new process, and then send a SC_MAXIMIZE system command message to it. You can get the handle through the Process.MainWindowHandle property. To send a message you should use the DllImportAttribute attribute to import the API function. This is a sample code:

public class WinAPI
{
	public const int WM_SYSCOMMAND = 0x0112;
	public const int SC_MAXIMIZE = 0xF030;

	[DllImportAttribute ('user32.dll')]
	public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
}

Process p = new Process();
p.StartInfo.FileName = @'D:\Program Files\test.exe';
p.Start();
WinAPI.SendMessage(p.MainWindowHandle, WinAPI.WM_SYSCOMMAND, WinAPI.SC_MAXIMIZE,0);

(from lion_noreply@microsoft.com on microsoft.public.dotnet.framework.windowsforms)

Permalink

Use the Process class found in the System.Diagnostic namespace.

	Process proc = new Process();
	
	// test.exe is a console application generated by VC6
	proc.StartInfo.FileName = @'C:\test\test.exe';

	proc.StartInfo.Arguments = '';
	proc.StartInfo.CreateNoWindow = true;
	proc.StartInfo.UseShellExecute = false;
	proc.StartInfo.RedirectStandardOutput = true;

	proc.Start();
	string output = proc.StandardOutput.ReadToEnd();

	//output now holds what text.exe would have displayed to the console
Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.