1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-05-12 14:34:08 +02:00

Rewrite tweet screenshot functionality to use native methods

This commit is contained in:
chylex 2017-03-13 21:40:15 +01:00
parent 69ea242408
commit 563c856dd3
3 changed files with 58 additions and 12 deletions

View File

@ -4,6 +4,9 @@
using TweetDck.Core.Bridge;
using TweetDck.Core.Controls;
using TweetDck.Resources;
using System.Drawing;
using System.Drawing.Imaging;
using TweetDck.Core.Utils;
namespace TweetDck.Core.Notification.Screenshot{
sealed class FormNotificationScreenshotable : FormNotificationBase{
@ -21,15 +24,30 @@ public void LoadNotificationForScreenshot(TweetNotification tweet, int width, in
browser.LoadHtml(tweet.GenerateHtml(enableCustomCSS: false), "http://tweetdeck.twitter.com/?"+DateTime.Now.Ticks);
Location = ControlExtensions.InvisibleLocation;
FormBorderStyle = Program.UserConfig.ShowScreenshotBorder ? FormBorderStyle.FixedToolWindow : FormBorderStyle.None;
SetNotificationSize(width, height);
}
public void TakeScreenshotAndHide(){
MoveToVisibleLocation();
Activate();
SendKeys.SendWait("%{PRTSC}");
bool border = Program.UserConfig.ShowScreenshotBorder;
IntPtr context = NativeMethods.GetDeviceContext(this, border);
if (context == IntPtr.Zero){
MessageBox.Show("Could not retrieve a graphics context handle for the notification window to take the screenshot.", "Screenshot Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else{
using(Bitmap bmp = new Bitmap(border ? Width : ClientSize.Width, border ? Height : ClientSize.Height, PixelFormat.Format32bppRgb)){
try{
NativeMethods.RenderSourceIntoBitmap(context, bmp);
}finally{
NativeMethods.ReleaseDeviceContext(this, context);
}
Clipboard.SetImage(bmp);
}
}
Reset();
}

View File

@ -4,14 +4,11 @@
namespace TweetDck.Core.Notification.Screenshot{
sealed class TweetScreenshotManager : IDisposable{
private readonly FormBrowser browser;
private readonly FormNotificationScreenshotable screenshot;
private readonly Timer timeout;
public TweetScreenshotManager(FormBrowser browser){
this.browser = browser;
this.screenshot = new FormNotificationScreenshotable(Callback, browser, NotificationFlags.DisableContextMenu | NotificationFlags.TopMost){
public TweetScreenshotManager(Form owner){
this.screenshot = new FormNotificationScreenshotable(Callback, owner, NotificationFlags.DisableContextMenu | NotificationFlags.TopMost){
CanMoveWindow = () => false
};
@ -31,10 +28,7 @@ private void Callback(){
}
timeout.Stop();
browser.PauseNotification();
screenshot.TakeScreenshotAndHide();
browser.ResumeNotification();
}
public void Dispose(){

View File

@ -1,4 +1,5 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
@ -45,6 +46,19 @@ private struct LASTINPUTINFO{
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO info);
[DllImport("user32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
@ -106,5 +120,25 @@ public static int GetIdleSeconds(){
int seconds = (int)Math.Floor(TimeSpan.FromMilliseconds(ticks-info.dwTime).TotalSeconds);
return Math.Max(0, seconds); // ignore rollover after several weeks of uptime
}
public static IntPtr GetDeviceContext(Form form, bool includeBorder){
return includeBorder ? GetWindowDC(form.Handle) : GetDC(form.Handle);
}
public static void RenderSourceIntoBitmap(IntPtr source, Bitmap target){
using(Graphics graphics = Graphics.FromImage(target)){
IntPtr graphicsHandle = graphics.GetHdc();
try{
BitBlt(graphicsHandle, 0, 0, target.Width, target.Height, source, 0, 0, 0x00CC0020);
}finally{
graphics.ReleaseHdc(graphicsHandle);
}
}
}
public static void ReleaseDeviceContext(Form form, IntPtr ctx){
ReleaseDC(form.Handle, ctx);
}
}
}