i'm working with the Solidworks Pdm Api and i'm developing an addin using Windows Forms to show information about some files.
In the api docs, recommend to use this class to set the Pdm window as parent
public class WindowHandle : IWin32Window
{
private IntPtr mHwnd;
public WindowHandle(int hWnd)
{
mHwnd = new IntPtr(hWnd);
}
public IntPtr Handle
{
get { return mHwnd; }
}
}
And it works well, so, when i will show my form, i'm doing the next
//i recived hWnd parameter from the api
WindowHandle myHandle = new WindowHandle(hWnd);
var weForm = new myForm();
weForm.StartPosition = FormStartPosition.CenterParent;
weForm.ShowDialog(myHandle);
At this point, the form shows without problem, the Pdm Window is effectively the parent, but the Form is not centered.
I found this question about how to center forms in his parent, but apparently anyone work when you use a custom class inherited from IWin32Window.
What can i do to center my form?
If the auto-centering feature isn't working then you'll need to do the math yourself.
The math basically means that you align the center points of each window.
int left = parentBounds.Left + (parentBounds.Width / 2) - (childBounds.Width / 2);
int right = parentBounds.Top + (parentBounds.Height / 2) - (childBounds.Height / 2);
Related
I'm working in a company where the owner wish take a screenshot of a windows mail app; specifically the section where the e-mail are show; and if the window or the section have an scroll, then must avoid it and take the screenshot of that whole section.
I'm building it on a .net console app, and I have download a lot of examples where shows just how to take a screeshot of an specific or any window.
The closest code (I think) that I found was this:
IntPtr current = IntPtr.Zero;
IntPtr handle = IntPtr.Zero;
List<IntPtr> thumbs = new List<IntPtr>();
if (handle == IntPtr.Zero)
handle = ((System.Windows.Interop.HwndSource)System.Windows.Interop.HwndSource.FromVisual(this)).Handle;
current = DWM.GetWindow(handle, DWM.GetWindowCmd.First);
do
{
int GWL_STYLE = -16;
int TASKSTYLE = 0x10000000 | 0x00800000;
if (TASKSTYLE == (TASKSTYLE & DWM.GetWindowLong(current, GWL_STYLE)))
{
thumbs.Add(current);
}
current = DWM.GetWindow(current, DWM.GetWindowCmd.Next);
if (current == handle)
current = DWM.GetWindow(current, DWM.GetWindowCmd.Next);
}
while (current != IntPtr.Zero);
this.DataContext = thumbs;
What customer expects it's to take an screenshot of a windows mail app but as I said before, the section that shows the e-mail in fact. So, it must looks something like:
Result
I am not sure how to do it from a Console Application, as that is very limited, but you can create a screen capture program from Windows Forms significantly easier.
The course I took from Huw Collingbourne who will teach you how to do it. It is not a small program to type out in this box though.
The program he teaches had a mainform, then would pop up a smaller transparent form that you would maneuver over the area you want to capture. To capture you would press the button which would capture the transparent form with this code:
formRect = new Rectangle(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height);
this.Hide();
mainForm.GrabRect(formRect);
Going back to the main form the program would put the picture on the picturebox for you to view.
public void GrabRect(Rectangle rect)
{
int rectWidth = rect.Width - rect.Left;
int rectHeight = rect.Height - rect.Top;
Bitmap bm = new Bitmap(rectWidth, rectHeight);
Graphics g = Graphics.FromImage(bm);
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, new Size(rectWidth, rectHeight));
this.pb_screengrab.Image = bm;
Clipboard.SetImage(bm);
g.Dispose();
}
Here are the links to his course
https://bitwisecourses.com/p/program-a-screen-capture-tool-in-c-sharp
and his course sold through udemy
https://www.udemy.com/course/program-a-screen-capture-tool-in-c/learn/lecture/15760316#content
bitwisecourses.com is his direct website I believe. Otherwise Udemy will offer nice discounts like $10-$13 for their various classes. Once you bought a bunch and don’t do anything for a few months they will try to charge you full price, but you only need to email them and they will start discounting you again.
I put everything I did here: https://github.com/johnbnstx/HuwBurn_ScreenGrab
I hope this helps.
How do you create the transparency effects that you see in windows 10? Something like this:
I have no clue how to approach this in c#. Logically thinking I would take a snapshot of the desktop every time the form comes into focus. Then blur it and place it at 0, 0(screen to client coordinates). That doesn't seem very effective. Any help? Again. not an experienced C# programmer, so a detailed explanation would be much appreciated
Edit: I saw some the answers referring me to a page for alpha blending. This is not what I am looking for. I wanted to know how to create the blur that you see in the image, the rest I can figure out at my own pace
Though all of the comments and the answers say it is not possible for WinForms, it definitely works also for WinForms (as SetWindowCompositionAttribute can be called on a Win32 window handle):
internal enum AccentState
{
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_INVALID_STATE = 4
}
internal enum WindowCompositionAttribute
{
WCA_ACCENT_POLICY = 19
}
[StructLayout(LayoutKind.Sequential)]
internal struct AccentPolicy
{
public AccentState AccentState;
public int AccentFlags;
public int GradientColor;
public int AnimationId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct WindowCompositionAttributeData
{
public WindowCompositionAttribute Attribute;
public IntPtr Data;
public int SizeOfData;
}
internal static class User32
{
[DllImport("user32.dll")]
internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
}
And then in your Form constructor:
public Form1()
{
InitializeComponent();
BackColor = Color.Black; // looks really bad with the default back color
var accent = new AccentPolicy { AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND };
var accentStructSize = Marshal.SizeOf(accent);
var accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
var data = new WindowCompositionAttributeData
{
Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY,
SizeOfData = accentStructSize,
Data = accentPtr
}
User32.SetWindowCompositionAttribute(Handle, ref data);
Marshal.FreeHGlobal(accentPtr);
}
Result:
Windows Forms doesn't support AcrylicBrush so far. Only UWP support this.
But you have a Win32 API SetWindowCompositionAttribute to simulate this behavior.
The SetWindowCompositionAttribute API
By calling the Windows internal API SetWindowCompositionAttribute, you can get a lightly blurred transparent Window but this transparency is much less than the AcyclicBrush.
How to implement it
Calling SetWindowCompositionAttribute API is not very easy, so I've written a wrapper class for easier usage. But it's for WPF only.
I've written two posts talking about this:
https://walterlv.github.io/post/win10/2017/10/02/wpf-transparent-blur-in-windows-10.html (not in English)
3 Ways to create a window with blurring background on Windows 10 - walterlv
Other options
It's recommended to use AcrylicBrush using UWP and you can read Microsoft's documents Acrylic material - UWP app developer | Microsoft Docs for more details about it.
You can get that by using some algorithms
I don't know will it work or not. When I see your post I just think and got this concept.
Get entire windows desktop wallpaper image by using copyscreen method
Draw that image into a new bitmap where bitmap width = screen resolution.width and bitmap height = screen resolution.height eg: Bitmap bm = new Bitmap (1920, 1080)
Learn how to blur a bitmap image in c#. There is many of blogs teaching how to blur a bitmap programmatically.
Make blur of captured desktop wallpaper image
Put a picture of inside the form and draw the blurred bitmap into picturebox
You can make FormBorderStyle.None to get rid of old borders
You should keep picturebox picture style = normal in order to get full blurred image
I'm using OpenTK to make a C# OpenGL application.
I'm trying not to use the GameWindow class to open a context - here is my class managing a window + context :
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Platform;
using OpenTK.Input;
class Window
{
private INativeWindow window_;
private IGraphicsContext context_;
private bool isExiting_;
public Window(int width, int height, bool fullscreen, string title = "StormEngine application")
{
window_ = new NativeWindow(width, height, title, fullscreen ? GameWindowFlags.Fullscreen : GameWindowFlags.FixedWindow, GraphicsMode.Default, DisplayDevice.Default);
context_ = new GraphicsContext(GraphicsMode.Default, window_.WindowInfo, 4, 4, GraphicsContextFlags.Default);
context_.MakeCurrent(window_.WindowInfo);
window_.Visible = true;
window_.KeyDown += (sender, e) =>
{
if (e.Keyboard[Key.Escape])
window_.Close();
};
isExiting_ = false;
}
public Window(int width, int height) : this(width, height, false) { }
public bool EndFrame()
{
context_.SwapBuffers();
window_.ProcessEvents();
return (window_.Exists && !isExiting_);
}
}
I'm then calling Window w = new Window(800, 480); to open a window.
But as soon as I make a call to an OpenGL method, in my case int programId = GL.CreateProgram();, I am given a AccessViolationException.
My guess is that OpenGL function pointers are not loaded correctly, but I cannot find where the problem happens (I get no information about what happens inside GL.CreateProgam()).
Any idea of what might be happening, why, and how to resolve that ? :)
Forget it, I found my mistake :)
In OpenTK, a GraphicsContext needs, once created and made current, to be loaded.
To do so, just after context_.MakeCurrent(window_.WindowInfo);, I added :
(context_ as IGraphicsContextInternal).LoadAll()
I had to figure it out from the GameWindow class source on Github, tho, because this way to create a window isn't documented at all ^^
And it now works like a charm. :)
This is a duplicate of a question I posted at Windows Dev Center. Still awaiting replies, so I thought I would try it here. My apologies if the formatting goes awry.
This is currently being written and debugged using Windows 7 Professional, SP1.
The application is located at the top of the desktop, and the working area is appropriately resized via a hook into the SystemParametersInfo function. The MenuStrip appears as it should, with the exception that any dropdown from the MenuStrip shows as detached from the MenuStrip itself (as if it is being drawn on the new working area, as opposed to the form containing the MenuStrip). For example:
Application TopLevel: true
Application Height: 150
Application Location: 0,0 on Desktop (prior to working area's resize)
MenuStrip Height: 25
MenuStrip Location: 0,0 inside Parent Form
MenuStrip DropDown Location: x,2 (where x is a valid and acceptable value) this is being drawn on the resized working area (i.e. beneath the form)
I have attempted correcting this with a custom Renderer to no present avail. I tried to override WndProc (as follows) so as to see what exactly was occurring, but that resulted in a stackoverflow halfway through drawing the application.
protected override void WndProc(ref Message m)
{
if (mainForm.Visible)
{
MessageBox.Show("ID: " + m.Msg.ToString() + "\n" + m.ToString());
}
base.WndProc(ref m);
}
I suspect I've run this into the ground by now, but if you require any further explanation, just let me know. Just hoping someone can point me in the appropriate direction as to where I should look.
Hopefully this will answer the question regarding why I used SystemParametersInfo:
#region TEMPORARY FIX TO ACHIEVE APPBAR
public RECT normalWorkingRECT = new RECT();
public RECT newWorkingRECT = new RECT();
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
};
[DllImport("user32.dll", EntryPoint="SystemParametersInfo")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref RECT pvParam, uint fWinIni);
//call after scale is set
private void setAppBar()
{
//make the parent = the desktop
if (!this.GetTopLevel())
{
this.SetTopLevel(true);
}
this.Width = SystemInformation.PrimaryMonitorSize.Width;
//set old Working Area
SystemParametersInfo(0x0030, 0, ref normalWorkingRECT, 0);
//change work area based on size of main form
newWorkingRECT.left = normalWorkingRECT.left;
newWorkingRECT.top = normalWorkingRECT.top + this.DesktopBounds.Height + 4;
newWorkingRECT.right = normalWorkingRECT.right;
newWorkingRECT.bottom = normalWorkingRECT.bottom;
SystemParametersInfo(0x002F, 0, ref newWorkingRECT, 0x0002);
}
//called on close
private void unsetAppBar()
{
//get current work area to compare
RECT testRECT = new RECT();
SystemParametersInfo(0x0030, 0, ref testRECT, 0);
//if no change, resize to normal working rect
if (newWorkingRECT.top == testRECT.top &&
newWorkingRECT.bottom == testRECT.bottom &&
newWorkingRECT.left == testRECT.left &&
newWorkingRECT.right == testRECT.right)
{
SystemParametersInfo(0x002F, 0, ref normalWorkingRECT, 0x0002);
}
//if there is a change, resize to current working rect - this.height
else
{
testRECT.top -= this.DesktopBounds.Height + 4;
SystemParametersInfo(0x002F, 0, ref testRECT, 0x0002);
}
}
#endregion
EDIT: Added image as requested and code to show reason for SystemParametersInfo.
How can I make floating windows use their design size (and not the Dock Panel Suite's default size) with the Weifenluo Dock Panel suite?
Hint: I tried a proposition from the Dock Panel Suite forums at SF.net, but that doesn't seem to work.
I stumbled across this question when looking for the answer myself, and found Timothy's answer to not work for me.
The problem was that the method he outlines also floated the window by default. (maybe that's a version difference)
I have solved this another way. I've created a base class that inherits from DockContent that all my document windows would inherit from. I then created another overload for the Show method that handles this (I used the DockPanelSuite source code to help build this method).
public void Show(DockPanel dockPanel, DockState dockState, Rectangle floatWindowBounds)
{
Show(dockPanel, dockState); //shows the panel like normal
//now for the part to initialize the float pane and size
if (DockHandler.FloatPane == null)
{
DockHandler.FloatPane = dockPanel.DockPaneFactory.CreateDockPane(this, DockState.Float, false);
DockHandler.FloatPane.FloatWindow.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
}
DockHandler.FloatPane.FloatWindow.Bounds = floatWindowBounds;
}
when CForm is derived from DockContent,
I have a method within my MDIContainerWindow which looks like this
public void ShowForm(CForm pForm)
{
pForm.MdiParent = this;
Size lS = pForm.Size;
dockPanel.DefaultFloatWindowSize = lS;
pForm.Show(dockPanel);
pForm.VisibleState = DockState.Float;
}
This is working for me (in VB):
Dim MyForm As New MyForm
MyForm.Show(DockPanel, New Rectangle(MyForm.Location, MyForm.Size))
MyForm.DockState = DockState.DockRight
This worked for me:
var topLeft = dockPanel1.Location;
topLeft.X += (dockPanel1.Size.Width / 2 - newForm.Size.Width / 2);
topLeft.Y += (dockPanel1.Size.Height / 2 - newForm.Size.Height / 2);
newForm.Show(dockPanel1, new Rectangle(topLeft, newForm.Size));