Skip to content

Commit b11b2f1

Browse files
committed
Fixed the wallpaper rendering error when the main display is on the right.
1 parent 26d48e6 commit b11b2f1

File tree

10 files changed

+186
-27
lines changed

10 files changed

+186
-27
lines changed

AwesomeWallpaper/AwesomeWallpaper.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
<Reference Include="System.ComponentModel.Composition" />
7676
<Reference Include="System.ComponentModel.DataAnnotations" />
7777
<Reference Include="System.Data" />
78+
<Reference Include="System.Drawing" />
7879
<Reference Include="System.Management" />
7980
<Reference Include="System.Windows.Forms" />
8081
<Reference Include="System.Xml" />
@@ -120,6 +121,7 @@
120121
<Compile Include="Settings\WallpaperType.cs" />
121122
<Compile Include="StartUpManager.cs" />
122123
<Compile Include="Utils\AssemblyUtils.cs" />
124+
<Compile Include="Utils\ImageUtils.cs" />
123125
<Compile Include="Utils\SerializeUtils.cs" />
124126
<Compile Include="Utils\SystemInformationUtils.cs" />
125127
<Compile Include="Utils\WindowUtils.cs" />

AwesomeWallpaper/MainWindow.xaml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@
55
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
66
xmlns:local="clr-namespace:AwesomeWallpaper"
77
mc:Ignorable="d"
8-
AllowsTransparency="True"
98
WindowStyle="None"
10-
Background="{x:Null}"
11-
IsHitTestVisible="{Binding IsHitTestVisible}"
129
ResizeMode="NoResize"
1310
Loaded="Window_Loaded"
14-
Closing="Window_Closing"
15-
ShowInTaskbar="False"
16-
Opacity="{Binding Opacity}">
17-
<Grid x:Name="GridContainer">
11+
Closing="Window_Closing"
12+
IsHitTestVisible="{Binding IsHitTestVisible}"
13+
ShowInTaskbar="False">
14+
<Grid x:Name="GridContainer" Opacity="{Binding Opacity}">
1815
</Grid>
1916
</Window>

AwesomeWallpaper/MainWindow.xaml.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,62 @@
22
using System.Runtime.InteropServices;
33
using System.Windows;
44
using System.Windows.Interop;
5-
using AwesomeWallpaper.Utils;
5+
using System.Windows.Media;
6+
using System.Windows.Forms;
67
using static AwesomeWallpaper.NativeConstants;
78
using static AwesomeWallpaper.NativeMethods;
9+
using static AwesomeWallpaper.Utils.WindowUtils;
10+
using static AwesomeWallpaper.Utils.ImageUtils;
811

912
namespace AwesomeWallpaper
1013
{
1114
public partial class MainWindow : Window
1215
{
1316
public bool AllowClose { get; set; } = false;
1417

18+
public int MonitorLeft { get; set; }
19+
20+
public int MonitorTop { get; set; }
21+
22+
public int MonitorWidth { get; set; }
23+
24+
public int MonitorHeight { get; set; }
25+
1526
public MainWindow()
1627
{
1728
InitializeComponent();
1829
}
1930

2031
private void Window_Loaded(object sender, RoutedEventArgs e)
2132
{
33+
var screens = Screen.AllScreens;
2234
var handle = new WindowInteropHelper(this).Handle;
23-
WindowUtils.SetStyles(handle);
24-
WindowUtils.ShowAlwaysOnDesktopBehindIcons(handle);
35+
SetStyles(handle);
36+
SendMessageToProgman();
37+
var workerWHandle = GetWorkerW(handle);
38+
var rect = new Rect();
39+
SetWindowPos(handle, (IntPtr)1, MonitorLeft, MonitorTop, MonitorWidth, MonitorHeight, 0 | 0x0010);
40+
MapWindowPoints(handle, workerWHandle, ref rect, 2);
41+
SetParent(handle, workerWHandle);
42+
SetWindowPos(handle, (IntPtr)1, rect.Left, rect.Top, MonitorWidth, MonitorHeight, 0 | 0x0010);
43+
var imageBrush = new ImageBrush();
44+
using (var image = CaptureWindow(workerWHandle, rect.Left, rect.Top, MonitorWidth, MonitorHeight))
45+
{
46+
imageBrush.ImageSource = ConvertImageToBitmapSource(image);
47+
Background = imageBrush;
48+
}
49+
RefreshDesktop();
2550
var hwndSource = HwndSource.FromHwnd(handle);
2651
hwndSource.AddHook(WindowProc);
2752
}
2853

2954
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
3055
{
3156
e.Cancel = !AllowClose;
57+
if (e.Cancel)
58+
{
59+
RefreshDesktop();
60+
}
3261
}
3362

3463
private unsafe IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)

AwesomeWallpaper/NativeConstants.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,9 @@ static class NativeConstants
1212
public const int SWP_NOZORDER = 4;
1313
public const int WM_WINDOWPOSCHANGING = 0x46;
1414
public const int WM_DPICHANGED = 0x02E0;
15+
public const uint SPI_SETDESKWALLPAPER = 20;
16+
public const uint SPIF_UPDATEINIFILE = 0x1;
17+
public const uint SPI_SETCLIENTAREAANIMATION = 0x1043;
18+
public const int SRCCOPY = 0x00CC0020;
1519
}
1620
}

AwesomeWallpaper/NativeMethods.cs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Runtime.InteropServices;
33
using System.Security;
44
using System.Text;
5+
using System.Drawing;
56

67
namespace AwesomeWallpaper
78
{
@@ -35,7 +36,7 @@ static class NativeMethods
3536
[DllImport("user32")]
3637
public static extern IntPtr GetDesktopWindow();
3738

38-
[DllImport("psapi", SetLastError = true)]
39+
[DllImport("psapi")]
3940
public static extern bool GetPerformanceInfo(ref PerformanceInformation pi, int size);
4041

4142
[DllImport("kernel32")]
@@ -45,7 +46,7 @@ static class NativeMethods
4546
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
4647

4748
[DllImport("user32")]
48-
public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);
49+
public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpWindowClass, string lpWindowName);
4950

5051
[DllImport("user32")]
5152
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
@@ -61,5 +62,47 @@ static class NativeMethods
6162

6263
[DllImport("user32")]
6364
public static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
65+
66+
[DllImport("user32.dll")]
67+
public static extern int SendMessageTimeout(IntPtr hWnd, int wMsg, int wParam, int lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out int lpdwResult);
68+
69+
[DllImport("user32.dll", CharSet = CharSet.Auto)]
70+
public static extern int SystemParametersInfo(uint uiAction, uint uiParam, string pvParam, uint fWinIni);
71+
72+
[DllImport("user32.dll")]
73+
public static extern int GetWindowRect(IntPtr hwnd, out Rect rect);
74+
75+
[DllImport("user32.dll")]
76+
public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
77+
78+
[DllImport("user32")]
79+
public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref Rect rect, [MarshalAs(UnmanagedType.U4)] int cPoints);
80+
81+
[DllImport("user32")]
82+
public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref Point pt, [MarshalAs(UnmanagedType.U4)] int cPoints);
83+
84+
[DllImport("gdi32.dll")]
85+
public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop);
86+
87+
[DllImport("gdi32.dll")]
88+
public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
89+
90+
[DllImport("gdi32.dll")]
91+
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
92+
93+
[DllImport("gdi32.dll")]
94+
public static extern bool DeleteDC(IntPtr hDC);
95+
96+
[DllImport("gdi32.dll")]
97+
public static extern bool DeleteObject(IntPtr hObject);
98+
99+
[DllImport("gdi32.dll")]
100+
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
101+
102+
[DllImport("user32.dll")]
103+
public static extern IntPtr GetWindowDC(IntPtr hWnd);
104+
105+
[DllImport("user32.dll")]
106+
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
64107
}
65-
}
108+
}

AwesomeWallpaper/NativeTypes.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,14 @@ public void Init()
7272
cbSize = (uint)Marshal.SizeOf(this);
7373
}
7474
}
75-
}
75+
76+
[Flags]
77+
public enum SendMessageTimeoutFlags : uint
78+
{
79+
SMTO_NORMAL = 0x0,
80+
SMTO_BLOCK = 0x1,
81+
SMTO_ABORTIFHUNG = 0x2,
82+
SMTO_NOTIMEOUTIFNOTHUNG = 0x8,
83+
SMTO_ERRORONEXIT = 0x20
84+
}
85+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Windows;
3+
using System.Windows.Interop;
4+
using System.Drawing;
5+
using System.Windows.Media.Imaging;
6+
using static AwesomeWallpaper.NativeMethods;
7+
8+
namespace AwesomeWallpaper.Utils
9+
{
10+
static class ImageUtils
11+
{
12+
public static BitmapSource ConvertImageToBitmapSource(Image image)
13+
{
14+
using (var bitmap = new Bitmap(image))
15+
{
16+
var hBitmap = bitmap.GetHbitmap();
17+
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
18+
bitmapSource.Freeze();
19+
DeleteObject(hBitmap);
20+
return bitmapSource;
21+
}
22+
}
23+
}
24+
}

AwesomeWallpaper/Utils/WindowUtils.cs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Drawing;
23
using static AwesomeWallpaper.NativeConstants;
34
using static AwesomeWallpaper.NativeMethods;
45

@@ -13,24 +14,29 @@ static class WindowUtils
1314
/// WorkerW behind the desktop icons. If it is already there, nothing
1415
/// happens.
1516
/// </summary>
16-
public static void ShowAlwaysOnDesktopBehindIcons(IntPtr hwnd)
17+
public static void SendMessageToProgman()
1718
{
1819
var progmanHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Progman", null);
19-
SendMessage(progmanHandle, 0x052C, 0x0000000D, 0);
20-
SendMessage(progmanHandle, 0x052C, 0x0000000D, 1);
20+
var result = 0;
21+
SendMessageTimeout(progmanHandle, 0x052C, 0, 0, SendMessageTimeoutFlags.SMTO_NORMAL, 1000, out result);
22+
//SendMessage(progmanHandle, 0x052C, 0, 0);
23+
//SendMessage(progmanHandle, 0x052C, 0x0000000D, 0);
24+
//SendMessage(progmanHandle, 0x052C, 0x0000000D, 1);
25+
}
2126

27+
public static IntPtr GetWorkerW(IntPtr hwnd)
28+
{
2229
var workerWHandle = IntPtr.Zero;
2330
EnumWindows(new EnumWindowsProc((topHandle, topParamHandle) =>
2431
{
25-
IntPtr shellHandle = FindWindowEx(topHandle, IntPtr.Zero, "SHELLDLL_DefView", null);
32+
var shellHandle = FindWindowEx(topHandle, IntPtr.Zero, "SHELLDLL_DefView", null);
2633
if (shellHandle != IntPtr.Zero)
2734
{
2835
workerWHandle = FindWindowEx(IntPtr.Zero, topHandle, "WorkerW", null);
2936
}
3037
return true;
3138
}), IntPtr.Zero);
32-
workerWHandle = workerWHandle == IntPtr.Zero ? progmanHandle : workerWHandle;
33-
SetParent(hwnd, workerWHandle);
39+
return workerWHandle;
3440
}
3541

3642
public static void SetStyles(IntPtr hwnd)
@@ -54,5 +60,47 @@ public static void EnableNoActive(IntPtr hwnd, bool enable)
5460
}
5561
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle);
5662
}
63+
64+
public static void RefreshDesktop()
65+
{
66+
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, null, SPIF_UPDATEINIFILE);
67+
}
68+
69+
public static Image CaptureWindow(IntPtr hwnd, int x, int y, int width, int height)
70+
{
71+
// get te hDC of the target window
72+
var hdcSrc = GetWindowDC(hwnd);
73+
74+
// get the size
75+
var windowRect = new Rect();
76+
GetWindowRect(hwnd, out windowRect);
77+
78+
// create a device context we can copy to
79+
var hdcDest = CreateCompatibleDC(hdcSrc);
80+
81+
// create a bitmap we can copy it to,
82+
// using GetDeviceCaps to get the width/height
83+
var hBitmap = CreateCompatibleBitmap(hdcSrc, width, height);
84+
85+
// select the bitmap object
86+
var hOld = SelectObject(hdcDest, hBitmap);
87+
88+
// bitblt over
89+
BitBlt(hdcDest, 0, 0, width, height, hdcSrc, x, y, SRCCOPY);
90+
91+
// restore selection
92+
SelectObject(hdcDest, hOld);
93+
94+
// clean up
95+
DeleteDC(hdcDest);
96+
ReleaseDC(hwnd, hdcSrc);
97+
98+
// get a .NET image object for it
99+
var image = Image.FromHbitmap(hBitmap);
100+
101+
// free up the Bitmap object
102+
DeleteObject(hBitmap);
103+
return image;
104+
}
57105
}
58106
}

AwesomeWallpaper/ViewManager.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ public void CreateViews()
8585
window.Hide();
8686
}
8787

88+
WindowUtils.RefreshDesktop();
89+
8890
EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, (IntPtr hMonitor, IntPtr hdcMonitor, ref Rect rect, IntPtr data) =>
8991
{
9092
if (Settings.Monitor == null || Settings.Monitor == windows)
@@ -103,10 +105,10 @@ public void CreateViews()
103105
(UserControl)new GalleryView();
104106
var mainWindow = new MainWindow
105107
{
106-
Left = info.rcMonitor.Left,
107-
Top = info.rcMonitor.Top,
108-
Width = info.rcMonitor.Width,
109-
Height = info.rcMonitor.Height,
108+
MonitorLeft = info.rcMonitor.Left,
109+
MonitorTop = info.rcMonitor.Top,
110+
MonitorWidth = info.rcMonitor.Width,
111+
MonitorHeight = info.rcMonitor.Height,
110112
DataContext = viewModel,
111113
};
112114
mainWindow.GridContainer.Children.Add(view);

AwesomeWallpaper/Views/VideoView.xaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
</UserControl.CommandBindings>
1616
<Grid VerticalAlignment="{Binding Settings.VideoVerticalAlignment}" HorizontalAlignment="{Binding Settings.VideoHorizontalAlignment}" MouseWheel="Grid_MouseWheel">
1717
<Grid.RowDefinitions>
18-
<RowDefinition Height="Auto" />
19-
<RowDefinition Height="Auto" />
20-
<RowDefinition Height="Auto" />
18+
<RowDefinition Height="0" />
19+
<RowDefinition Height="*" />
20+
<RowDefinition Height="0" />
2121
</Grid.RowDefinitions>
2222
<Grid.ColumnDefinitions>
2323
<ColumnDefinition Width="1*" />

0 commit comments

Comments
 (0)