I am experimenting and trying to figure out DWM and Windows Aero. So far, I think I pretty much have it, all except for some strange reason, when I click the thicker part of my form, my click goes right through it, and I can't figure out how to stop it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int en;
public Form1()
{
InitializeComponent();
DwmIsCompositionEnabled(ref en);
if (en > 0 && System.Environment.OSVersion.Version.Major >= 6)
{
en = 0;
MARGINS mg = new MARGINS();
mg.m_Buttom = 0;
mg.m_Left = 0;
mg.m_Right = 0;
mg.m_Top = 25;
DwmExtendFrameIntoClientArea(this.Handle, ref mg);
this.BackColor = Color.Magenta;
this.TransparencyKey = Color.Magenta;
}
}
public struct MARGINS
{
public int m_Left;
public int m_Right;
public int m_Top;
public int m_Buttom;
}
[System.Runtime.InteropServices.DllImport("dwmapi.dll")]
public extern static int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margin);
[System.Runtime.InteropServices.DllImport("dwmapi.dll")]
public extern static int DwmIsCompositionEnabled(ref int en);
}
}
That's because you have
this.BackColor = Color.Magenta;
this.TransparencyKey = Color.Magenta;
Remove line with transparency. This also happens in WindowsForms. I think it's by design, not bug.
Related
I need to set the background of a Windows form to the user's current Desktop wallpaper. How do I do this in C#?
Thanks
You can try the following code. I've tested this code on windows 8 and it works for me:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StringFormatting
{
public partial class WallpaperTest : Form
{
private const UInt32 SPI_GETDESKWALLPAPER = 0x73;
private const int MAX_PATH = 260;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SystemParametersInfo(UInt32 uAction, int uParam, string lpvParam, int fuWinIni);
public WallpaperTest()
{
InitializeComponent();
this.BackgroundImage = GetCurrentDesktopWallpaper();
this.BackgroundImageLayout = ImageLayout.Stretch;
}
public Image GetCurrentDesktopWallpaper()
{
string currentWallpaper = new string('\0', MAX_PATH);
SystemParametersInfo(SPI_GETDESKWALLPAPER, currentWallpaper.Length, currentWallpaper, 0);
string imageAddress = currentWallpaper.Substring(0, currentWallpaper.IndexOf('\0'));
return Image.FromFile(imageAddress);
}
}
}
I was making a small program that shows if numlock or capslock was on or off (because my laptop doesn't have those LEDs so I touhgt it would be interesting to make something like this). What I was trying to achieve is that text would change if key was pressed or not. What I have so far is program showing if they was on or off before running the program it self. How to make program react to changes?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern short GetKeyState(int keyCode);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
looper();
}
public void looper()
{
cLock_check();
nLock_check();
sLock_check();
}
public void cLock_check()
{
bool CapsLock = (((ushort)GetKeyState(0x14)) & 0xffff) != 0;
if (CapsLock)
lbl_cLock_onOff.Text = "ON";
else
lbl_cLock_onOff.Text = "OFF";
}
public void nLock_check()
{
bool NumLock = (((ushort)GetKeyState(0x90)) & 0xffff) != 0;
if (NumLock)
lbl_nLock_onOff.Text = "ON";
else
lbl_nLock_onOff.Text = "OFF";
}
public void sLock_check()
{
bool ScrollLock = (((ushort)GetKeyState(0x91)) & 0xffff) != 0;
if (ScrollLock)
lbl_sLock_onOff.Text = "ON";
else
lbl_sLock_onOff.Text = "OFF";
}
}
}
You should implement a global keyboard hook, as described in this article. Compare vkCode to VK_NUMLOCK, VK_CAPITAL and VK_SCROLL and call your relevant update function.
Create a timer object, give it a reasonable interval (For most 'responsive' UI issues 300 msec is appropriate), and set the Tick handler to call the looper method:
Timer checkState;
public Form1()
{
InitializeComponent();
checkState = new Timer { Interval = 300};
checkState.Tick += (o,e) => looper();
chechState.Start();
}
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test {
class Program {
static void Main(string[] args) {
for (int i = 0; i < 1000000000; i++) {
WindowHandler.testOverlay();
}
}
}
}
WindowHandler.cs:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Test {
static class WindowHandler {
private const String WINDOW_TITLE = "Minesweeper";
private static IntPtr windowHandle = IntPtr.Zero;
public static void testOverlay() {
if (windowHandle == IntPtr.Zero) {
windowHandle = getWindowHandle();
}
Graphics g = Graphics.FromHwnd(windowHandle);
g.FillRectangle(new SolidBrush(Color.White), 0, 0, 10000, 10000);
}
private static IntPtr getWindowHandle() {
foreach (Process proc in Process.GetProcesses()) {
if (proc.MainWindowTitle == WINDOW_TITLE) {
return proc.MainWindowHandle;
}
}
MessageBox.Show("Error: Unable to find window.");
return IntPtr.Zero;
}
}
}
I am not sure what I am doing wrong. I am writing a Minesweeper Solver and I am trying to overlay graphics on the Minesweeper window to provide debugging information. Unfortunately, it doesn't seem to work at all as I do not see any change on my screen. I am looping 1000000000 times in Program.cs just in case it erases my overlay on every frame refresh. I prefer to not try to hook DirectX.
I'm trying to capture a Screensaver event, however when I run my application it throws the following exception;
Unable to find an entry point named 'SystemParametersinfo' in DLL 'user32.dll'.
this is my code so far, any and all help would be greatly appreciated =D
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NLog;
using Topshelf;
using OsWatch;
using Microsoft.Win32;
using System.Runtime.InteropServices;
namespace NotifyIcon
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SystemParametersinfo(int uAction, int uParam, ref int ipvParam, int fuWinini);
const int SPI_GETSCREENSAVERRUNNING = 114;
static int screenSaverRunning = -1;
int ok = SystemParametersinfo(SPI_GETSCREENSAVERRUNNING, 0, ref screenSaverRunning, 0);
private void ScreenSaver()
{
if (ok == 0)
{
Logger.Trace("SCREENSAVER OFF");
}
if (screenSaverRunning != 0)
{
Logger.Trace("SCREENSAVER ON");
}
}
The following call to WNetAddConnection2 seems to hang forever. Note that the machine name is intentionally wrong - I'd like this to fail fast rather than block forever. Is there a way to achieve similar functionality but with a timeout?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[StructLayout(LayoutKind.Sequential)]
public class NETRESOURCE
{
public int dwScope;
public int dwType;
public int dwDisplayType;
public int dwUsage;
public string LocalName;
public string RemoteName;
public string Comment;
public string Provider;
}
[DllImport("mpr.dll")]
public static extern int WNetAddConnection2(NETRESOURCE netResource, string password, string username, int flags);
private void Form1_Load(object sender, EventArgs e)
{
NETRESOURCE myResource = new NETRESOURCE();
myResource.dwScope = 0;
myResource.dwType = 0; //RESOURCETYPE_ANY
myResource.dwDisplayType = 0;
myResource.LocalName = "";
myResource.RemoteName = #"\\invalid.machine.com";
myResource.dwUsage = 0;
myResource.Comment = "";
myResource.Provider = "";
int returnValue = WNetAddConnection2(myResource, "password", "username", 0); //hangs forever
Debug.Print("Finished connecting");
}
}
}
On earlier versions of Windows it was impossible to terminate a process that was stuck in one of the WNetAddConnection functions. This was fixed in Vista. According to Larry Osterman, the fix is the CancelSynchronousIo function.
The solution to your problem is:
Start a new thread to run WNetAddConnection2
Set a timer or wait in your existing thread.
After the timeout call CancelSynchronousIo specifying the handle of the connection thread.
I can't think of any reason why this would interact badly with .Net, but I haven't actually tried it...