Short Question:
How can I draw a copy of a hidden ActiveX control to a Bitmap?
Longer Question:
I have an ActiveX control which displays an Image. I would like to hide it behind something (example a panel), copy the display to a Bitmap so as to be able to process it (example access the pixels etc).
the trick is that you should use WM_PAINT
[Flags]
private enum DrawingOptions
{
PRF_CHECKVISIBLE = 0x00000001,
PRF_NONCLIENT = 0x00000002,
PRF_CLIENT = 0x00000004,
PRF_ERASEBKGND = 0x00000008,
PRF_CHILDREN = 0x00000010,
PRF_OWNED = 0x00000020
}
private const uint WM_PAINT = 0xF;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr dc, DrawingOptions opts);
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
using (Bitmap bm = new Bitmap(axChartSpace1.Width, axChartSpace1.Height))
{
using (Graphics g = Graphics.FromImage(bm))
{
IntPtr dc = g.GetHdc();
try
{
SendMessage(axChartSpace1.Handle, WM_PRINT, dc,
DrawingOptions.PRF_CLIENT |
DrawingOptions.PRF_NONCLIENT |
DrawingOptions.PRF_CHILDREN);
}
finally
{
g.ReleaseHdc();
}
bm.Save(#"C:\1.bmp");
}
}
}
Related
I have a MS Word Application Add-in written with VSTO. It contains a button used to create new Letter documents. When pressed a document is instantiated, a WPF dialog is displayed to capture information and then the information is inserted into the document.
On rare occasions, the WPF dialog slips behind MS Word. I then have to kill the Winword.exe process because the dialog is Modal.
I use the following code for my WPF dialog. The OfficeDialog sub class is used to make the dialog look like a MS-Word dialog.
var view = new LetterDetailsView(ViewModel);
view.ShowDialog();
public class OfficeDialog : Window
{
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
const int GWL_EXSTYLE = -20;
const int WS_EX_DLGMODALFRAME = 0x0001;
const int SWP_NOSIZE = 0x0001;
const int SWP_NOMOVE = 0x0002;
const int SWP_NOZORDER = 0x0004;
const int SWP_FRAMECHANGED = 0x0020;
const uint WM_SETICON = 0x0080;
const int ICON_SMALL = 0;
const int ICON_BIG = 1;
public OfficeDialog()
{
this.ShowInTaskbar = false;
}
public new void ShowDialog()
{
try
{
var helper = new WindowInteropHelper(this);
using (Process currentProcess = Process.GetCurrentProcess())
helper.Owner = currentProcess.MainWindowHandle;
base.ShowDialog();
}
catch (System.ComponentModel.Win32Exception ex)
{
Message.LogWarning(ex);
var helper = new WindowInteropHelper(this);
using (Process currentProcess = Process.GetCurrentProcess())
helper.Owner = currentProcess.MainWindowHandle;
base.ShowDialog();
}
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
RemoveIcon(this);
HideMinimizeAndMaximizeButtons(this);
}
public static void HideMinimizeAndMaximizeButtons(Window window)
{
const int GWL_STYLE = -16;
IntPtr hwnd = new WindowInteropHelper(window).Handle;
long value = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, (int)(value & -131073 & -65537));
}
public static void RemoveIcon(Window w)
{
// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(w).Handle;
// Change the extended window style to not show a window icon
int extendedStyle = OfficeDialog.GetWindowLong(hwnd, GWL_EXSTYLE);
OfficeDialog.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);
// reset the icon, both calls important
OfficeDialog.SendMessage(hwnd, WM_SETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
OfficeDialog.SendMessage(hwnd, WM_SETICON, (IntPtr)ICON_BIG, IntPtr.Zero);
// Update the window's non-client area to reflect the changes
OfficeDialog.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
static void SetCentering(Window win, IntPtr ownerHandle)
{
bool isWindow = IsWindow(ownerHandle);
if (!isWindow) //Don't try and centre the window if the ownerHandle is invalid. To resolve issue with invalid window handle error
{
//Message.LogInfo(string.Format("ownerHandle IsWindow: {0}", isWindow));
return;
}
//Show in center of owner if win form.
if (ownerHandle.ToInt32() != 0)
{
var helper = new WindowInteropHelper(win);
helper.Owner = ownerHandle;
win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
else
win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindow(IntPtr hWnd);
}
A modal dialog not being on top is the result of an incorrectly set owner. You already set the owner to the MainWindowHandle of the current process; however, in particular with multiple Word documents open, this might not be what you want.
I'd suggest to rely on the following property (introduced with Word 2013):
document.ActiveWindow.HWnd;
Apart from that there should not be the need to kill the Word process. It should be sufficient to minimize all windows (e.g. by pressing Windows Key + M)
What I am trying to do is just set my from, that has a picture box on it, to be the top most object on my computer and stay that way. I have tried to use f.topmost = true; but if when I click on something my form is no longer top most.
I am running my form from a dll (code of dll is below). I have also tried to add in a on load even to my form, which also did nothing.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace pic
{
public class Class1
{
[DllImport("user32.dll", SetLastError = true)]
private static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll")]
static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
public const int GWL_EXSTYLE = -20;
public const int WS_EX_LAYERED = 0x80000;
public const int WS_EX_TRANSPARENT = 0x20;
public const int LWA_ALPHA = 0x2;
public const int LWA_COLORKEY = 0x1;
Form f = new Form();
public void t(int LocalX, int LocalY, string PicLocal, byte transparency)
{
f.Load += new EventHandler(ProgramViwer_Load);
Bitmap bitmap;
// Form f = new Form();
f.BackColor = Color.White;
f.FormBorderStyle = FormBorderStyle.None;
f.Bounds = Screen.PrimaryScreen.Bounds;
bitmap = new Bitmap(PicLocal);
f.Size = new Size(bitmap.Size.Width, bitmap.Size.Height);
f.StartPosition = FormStartPosition.Manual;
f.SetDesktopLocation(LocalX, LocalY);
Application.EnableVisualStyles();
PictureBox PictureBox1 = new PictureBox();
PictureBox1.Location = new System.Drawing.Point(0, 0);
PictureBox1.Image = bitmap;
PictureBox1.Size = new System.Drawing.Size(bitmap.Size.Width, bitmap.Size.Height);
PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
f.Controls.Add(PictureBox1);
f.AllowTransparency = true;
SetWindowLong(f.Handle, GWL_EXSTYLE,
(IntPtr)(GetWindowLong(f.Handle, GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT));
// set transparency to 50% (128)
SetLayeredWindowAttributes(f.Handle, 0, transparency, LWA_ALPHA);
Color BackColor = Color.White;
f.TransparencyKey = BackColor;
f.Opacity = transparency / 255f;
Application.Run(f);
}
private void ProgramViwer_Load(object sender, EventArgs e)
{
f.TopMost = true;
}
}
}
Your problem is that other windows set their 'TopMost' property to true as well. It's not the cleanest solution but it should work.
new Thread(() =>
{
try
{
while (true)
{
this.TopMost = true;
Thread.Sleep(1);
}
}
catch (Exception ex) { }
}).Start();
I want to increase font size in DateTimePicker in Window Form C#. I want to set minimum 14 to 16 font size in DateTime picker.
I have tried below code but it's not working.
dateTimePicker1.CalendarFont = new Font("Courier New", 8.25F, FontStyle.Italic, GraphicsUnit.Point, ((Byte)(0)));
If you wish to retain visual styles for the other controls in your application, but disable for the date picker's drop down only, you can use the following code:
public class MyDateTimePicker : DateTimePicker
{
[DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
static extern Int32 SetWindowTheme(IntPtr hWnd, String textSubAppName, String textSubIdList);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
protected override void OnDropDown(EventArgs eventargs)
{
if (Application.RenderWithVisualStyles)
{
const int DTM_GETMONTHCAL = 0x1008;
//Get handle of calendar control - disable theming
IntPtr hCalendar = SendMessage(this.Handle, DTM_GETMONTHCAL, IntPtr.Zero, IntPtr.Zero);
if (hCalendar != IntPtr.Zero)
{
SetWindowTheme(hCalendar, "", "");
//Get handle of parent popup - resize appropriately
IntPtr hParent = GetParent(hCalendar);
if (hParent != IntPtr.Zero)
{
//The size you specify here will depend on the CalendarFont size chosen
MoveWindow(hParent, 0, 0, 400, 300, true);
}
}
}
base.OnDropDown(eventargs);
}
}
In main program delete / comment line Application.EnableVisualStyles();
and add new line of code after yours:
dateTimePicker1.Font = new Font("Courier New", 8.25F, FontStyle.Italic, GraphicsUnit.Point, ((Byte)(0)));
In iOS u have to make a renderer:
private void SetFont(CustomPicker view)
{
UIFont uiFont;
Control.Font = UIFont.SystemFontOfSize(11f); //the size which u want
}
In android you have to set the font for the renderer:
private void SetFont(CustomDatePicker view)
{
if (view.Font != Font.Default)
{
Control.TextSize = view.Font.ToScaledPixel();
Typeface font = Typeface.CreateFromAsset(Forms.Context.Assets,"Roboto-Bold.ttf");
Control.Typeface = font;
Control.Typeface = view.Font.ToTypeface();
}
}
I need to host my WPF UserControl in other window by Handle.
I've tried to use HwndSource:
var userControl = new MyUserControl();
var parameters = new HwndSourceParameters();
parameters.WindowStyle = 0x10000000 | 0x40000000;
parameters.SetPosition(5, 5);
parameters.SetSize(300, 300);
parameters.ParentWindow = parentWindowHwnd;
var src = new HwndSource(parameters);
src.RootVisual = userControl;
But in this case arrows and tab keys don't work.
If I use ElementHost everything is OK:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
var userControl = new UserControl1();
var elementHost = new ElementHost();
elementHost.Child = userControl;
elementHost.Left = 5;
elementHost.Top = 5;
elementHost.Width = 300;
elementHost.Height = 300;
SetParent(elementHost.Handle, parentWindowHwnd);
How can I get full functionality using HwndSource?
When you are using HwndSource you must register a handler for the windows messages.
this can done by call:
src.AddHook(this.messageHook);
The hook must check for wm_getdlgcode message.
private IntPtr messageHook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
{
switch (msg)
{
case WmGetDlgCode:
{
handled = true;
return (IntPtr)(DlgcWantChars | DlgcWantTab | DlgcWantArrows | DlgcWantAllKeys);
}
}
return IntPtr.Zero;
}
return via Dlgc_WantChars, Dlgc_WantTab, Dlgc_WantArrows and Dlgc_WantAllKeys what you need.
check this for the message and codes:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645425(v=vs.85).aspx
private const int WmGetDlgCode = 0x0087;
private const int DlgcWantChars = 0x0080;
private const int DlgcWantTab = 0x0002;
private const int DlgcWantAllKeys = 0x0004;
private const int DlgcWantArrows = 0x0001;
I am developing WinForms MDI app in VS2010 (.NET 4.0) and I just hate 3D border in MDI parent form.
So any ideas on how to remove it (make it flat or just no border it all) ?
I know this is an old post but I have spent some time and pain working the 3D border stuff out (because I needed it too) from fragments across the internet including:
Elements from Jacob Slusser's page at codeproject.com (Accessed 1st Aug'12)
So here goes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace MDITest
{
public static class MDIClientSupport
{
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", ExactSpelling = true)]
private static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
private const int GWL_EXSTYLE = -20;
private const int WS_EX_CLIENTEDGE = 0x200;
private const uint SWP_NOSIZE = 0x0001;
private const uint SWP_NOMOVE = 0x0002;
private const uint SWP_NOZORDER = 0x0004;
private const uint SWP_NOREDRAW = 0x0008;
private const uint SWP_NOACTIVATE = 0x0010;
private const uint SWP_FRAMECHANGED = 0x0020;
private const uint SWP_SHOWWINDOW = 0x0040;
private const uint SWP_HIDEWINDOW = 0x0080;
private const uint SWP_NOCOPYBITS = 0x0100;
private const uint SWP_NOOWNERZORDER = 0x0200;
private const uint SWP_NOSENDCHANGING = 0x0400;
public static bool SetBevel(this Form form, bool show)
{
foreach (Control c in form.Controls)
{
MdiClient client = c as MdiClient;
if (client != null)
{
int windowLong = GetWindowLong(c.Handle, GWL_EXSTYLE);
if (show)
{
windowLong |= WS_EX_CLIENTEDGE;
}
else
{
windowLong &= ~WS_EX_CLIENTEDGE;
}
SetWindowLong(c.Handle, GWL_EXSTYLE, windowLong);
// Update the non-client area.
SetWindowPos(client.Handle, IntPtr.Zero, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
return true;
}
}
return false;
}
}
}
In the form load event call:
form.SetBevel(false);
Don't forget to change the namespace and remember this is an extension method but it could be changed to be just a method call in another class or in you MDI parent form.
If you would prefer not to import external libraries there is also following cheat which repositions/resizes the mdi container control.
protected override void OnLoad(EventArgs e)
{
var mdiclient = this.Controls.OfType<MdiClient>().Single();
this.SuspendLayout();
mdiclient.SuspendLayout();
var hdiff = mdiclient.Size.Width - mdiclient.ClientSize.Width;
var vdiff = mdiclient.Size.Height - mdiclient.ClientSize.Height;
var size = new Size(mdiclient.Width + hdiff, mdiclient.Height + vdiff);
var location = new Point(mdiclient.Left - (hdiff / 2), mdiclient.Top - (vdiff / 2));
mdiclient.Dock = DockStyle.None;
mdiclient.Size = size;
mdiclient.Location = location;
mdiclient.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
mdiclient.ResumeLayout(true);
this.ResumeLayout(true);
base.OnLoad(e);
}
Try changing the FormBorderStyle property to FixedSingle