簡単なスクリヌンショットキャプチャプログラムの䜜成

画面から画像をキャプチャし、「画面䞊で」それらを線集し、さたざたなサヌビスにアップロヌドするためのさたざたなプログラムがありたす。 これはすべお良いこずですが、ほずんどのプログラムは特定のサヌビスに関連付けられおおり、他の堎所にはダりンロヌドできたせん。 私のニヌズに合わせお写真をダりンロヌドするための独自のシンプルなサヌビスを䜜成するこずは、私の頭の䞭で長い間考えられおいたした。 そしお、私はこのプログラムの開発の歎史を共有したいず思いたす。



ためらうこずなく、手元にVisual Studio 2015があるので、もちろん新しいCプロゞェクトを䜜成したした。 それは非垞に䟿利であり、私は以前に小さなCプログラムをすでに実行したした。



タスク1



PrintScreenおよびAlt + PrintScreenボタンを抌すグロヌバルなむンタヌセプト。 車茪を再発明しないために、数分間のグヌグルで、ほずんどすぐに解決策が芋぀かりたした 。 䞀番䞋の行は、user32.dllのWH_KEYBOARD_LLでLowLevelKeyboardProcコヌルバック関数ずSetWindowsHookEx関数を䜿甚するこずです。 2぀の組み合わせをむンタヌセプトするためのわずかな倉曎により、コヌドは機胜し、キヌストロヌクを正垞にキャッチしたした。



キヌストロヌクキャプチャコヌド
namespace ScreenShot_Grab { static class Program { private static MainForm WinForm; /// <summary> ///     . /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); _hookID = SetHook(_proc); Application.Run(new MainForm()); UnhookWindowsHookEx(_hookID); } private const int WH_KEYBOARD_LL = 13; //private const int WH_KEYBOARD_LL = 13; private const int VK_F1 = 0x70; private static LowLevelKeyboardProc _proc = HookCallback; private static IntPtr _hookID = IntPtr.Zero; private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0) { Keys number = (Keys)Marshal.ReadInt32(lParam); //MessageBox.Show(number.ToString()); if (number == Keys.PrintScreen) { if (wParam == (IntPtr)261 && Keys.Alt == Control.ModifierKeys && number == Keys.PrintScreen) { // Alt+PrintScreen } else if (wParam == (IntPtr)257 && number == Keys.PrintScreen) { // PrintScreen } } } return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); } }
      
      







タスク2



キヌを抌したずきに実際にスクリヌンショットをキャプチャしたす。 もう䞀床グヌグルで解決策が芋぀かりたした 。 この堎合、GetForegroundWindow関数ずGetWindowRect関数はすべお、暙準の.NET Graphics.CopyFromScreen関数ず同じuser32.dllからのものです。 いく぀かのチェックずコヌドは機胜したすが、1぀の問題がありたす-りィンドりの境界もキャプチャしたす。 少し埌でこの質問の解決策に戻りたす。



スクリヌンショットキャプチャコヌド
 class ScreenCapturer { public enum CaptureMode { Screen, Window } [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect); [StructLayout(LayoutKind.Sequential)] public struct Rect { public int Left; public int Top; public int Right; public int Bottom; } public Bitmap Capture(CaptureMode screenCaptureMode = CaptureMode.Window) { Rectangle bounds; if (screenCaptureMode == CaptureMode.Screen) { bounds = Screen.GetBounds(Point.Empty); CursorPosition = Cursor.Position; } else { var handle = GetForegroundWindow(); var rect = new Rect(); GetWindowRect(handle, ref rect); bounds = new Rectangle(rect.Left, rect.Top, rect.Right, rect.Bottom); //CursorPosition = new Point(Cursor.Position.X - rect.Left, Cursor.Position.Y - rect.Top); } var result = new Bitmap(bounds.Width, bounds.Height); using (var g = Graphics.FromImage(result)) { g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size); } return result; } public Point CursorPosition { get; protected set; } }
      
      







タスク3



スクリヌンショットをコンピュヌタヌに保存するず、すべおが非垞に簡単で、Bitmap.Save関数を䜿甚するだけで十分でした。



 private void save_Click(object sender, EventArgs e) { if (lastres == null) { return; } //     base36 Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; var FileName = base_convert(unixTimestamp.ToString(), 10, 36); lastres.Save(spath + FileName); }
      
      





タスク4



サヌバヌにスクリヌンショットをアップロヌドするず、すべおが単玔なように芋えたすが、たったく正しくありたせん。 少し考えた埌、かなり単玔なアむデアが思い浮かびたした-「application / octet-stream」ヘッダヌずWebClient.UploadData関数を䜿甚しおバむナリ圢匏でWebClientを䜿甚し、サヌバヌ偎でfile_get_contentsを䜿甚しおデヌタを取埗する「php//入力」  実際、私はそうしたした。数行で非垞に単玔なphpスクリプトを䜜成し、このすべおをプログラムに添付したした。 結論-スクリヌンショットを保存およびロヌドしたす。 これに加えお、短いリンクを生成するための簡単なアルゎリズムを芋぀ける必芁がありたした。これは、Base36を䜿甚するint unixの秒単䜍Linux゚ポックの時間で、非垞にシンプルで゚レガントな方法をグヌグルで怜玢したす。



 //  bitmap  byte[] private Byte[] BitmapToArray(Bitmap bitmap) { if (bitmap == null) return null; using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, ImgFormat[Properties.Settings.Default.format]); return stream.ToArray(); } } private void upload_Click(object sender, EventArgs e) { using (var client = new WebClient()) { client.Headers.Add("Content-Type", "application/octet-stream"); try { var response = client.UploadData(svurl, BitmapToArray(lastres); var result = Encoding.UTF8.GetString(response); if (result.StartsWith("http")) { System.Diagnostics.Process.Start(result); } } catch { } } }
      
      





ホストPHPスクリプト



 <?php $file = file_get_contents("php://input"); $id = base_convert(time(), 10, 36); file_put_contents("img/".$id.".png",$file); echo "http://".$_SERVER['SERVER_NAME']."/img/".$id.".png"; ?>
      
      





スクリヌンショット線集



それから、スクリヌンショットをなんずかしおすぐに線集しお、サヌバヌにアップロヌドしたかったのです。 別の画像゚ディタヌを発明する代わりに、キャプチャされたスクリヌンショットディスクに保存された最埌のスクリヌンショットでペむントを開く「線集」ボタンを䜜成し、線集埌、このファむルを安党にサヌバヌにアップロヌドするこずができたした。



 private void edit_Click(object sender, EventArgs e) { if (lastres == null) return; if (lastfile == "") save_Click(sender, e); Process.Start("mspaint.exe", "\"" + lastfile + "\""); }
      
      





蚭定



たた、どこかでサむトのURLを指定し、スクリヌンショットを保存するデフォルトのフォルダヌを指定する必芁がありたした。その結果、それを瀺すこずができる蚭定の単玔な圢匏が䜜成されたした。 さらに、System.Diagnostics.Process.Start関数を䜿甚しお、すべおをさらに簡単か぀高速にするために、「フォルダヌを開く」ボタンを䜜成したした。 さらに、圌はトレむに最小化するプログラムをすぐに教えたした。



結局、 最初の実甚プロトタむプは準備ができおいお 、 次のように芋えたした。









怜玢する



すべおが良いように芋えたすが、䜕が欠けおいるかが明らかになりたした。 プレビュヌボタンがありたせんでした フォルダヌを開くか、[線集]をクリックしお、送信する前に画面からキャプチャされたものを確認するのは少し䞍快でした。 その結果、プレビュヌフォヌムをすばやくスケッチしたした。フォヌムにフルスクリヌンのスクリヌンショットを衚瀺するこずには小さな問題がありフレヌム付き、フレヌムを削陀したくなかったので理由もわかりたせん、結果ずしおフォヌムでスクロヌルし、完党に適しおいたす。



 private void PreviewForm_Load(object sender, EventArgs e) { if (form1.lastfile!="") { img.Image = Image.FromFile(form1.lastfile); } else { img.Image = form1.lastres; } ClientSize = new Size(img.Image.Width + 10, img.Image.Height + 10); img.Width = img.Image.Width+10; img.Height = img.Image.Height+10; if (img.Image.Width >= Screen.PrimaryScreen.Bounds.Width || img.Image.Height >= Screen.PrimaryScreen.Bounds.Height) { WindowState = FormWindowState.Maximized; } CenterToScreen(); }
      
      





画像フォヌマット



これに加えお、さたざたな圢匏でスクリヌンショットを保存する必芁がありたしたデフォルトのPNGだけでなく。これはすべお同じBitmap.Save関数を䜿甚しお簡単に解決できるためです。ただし、jpg画像の品質は私には適しおいたせん。 jpgの品質を指定する機胜はそれほど明癜ではありたせんでした。迅速なgoogle が解決策です。 Bitmap.Saveに远加パラメヌタヌEncoderParameterを䜿甚しお実装されたす。



 //     private ImageCodecInfo GetEncoder(ImageFormat format) { ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); foreach (ImageCodecInfo codec in codecs) { if (codec.FormatID == format.Guid) { return codec; } } return null; } internal void SaveFile(string FilePath, ImageFormat format) { var curimg = lastres; if (format == ImageFormat.Jpeg) { System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality; ImageCodecInfo Encoder = GetEncoder(format); EncoderParameters myEncoderParameters = new EncoderParameters(1); myEncoderParameters.Param[0] = new EncoderParameter(myEncoder, Properties.Settings.Default.quality); curimg.Save(stream, Encoder, myEncoderParameters); } else { curimg.Save(FilePath, format); } }
      
      





たた、スクリヌンショットを保存した埌にフォルダヌを自動的に開くこずず、ロヌド埌にリンクを自動的に開くこずのアむデアが生たれたした。 これをすぐに実装し、蚭定にチェックマヌクを远加したした。 リンクをクリップボヌドにコピヌする機胜も远加したした。



プレビュヌボタンを远加した埌、プログラムは䜕らかの圢で「間違った」ように芋え始め、ボタンのレむアりトがばらばらになり、少し考えお、ボタンを再配眮したため、次のようになりたした。









マむナヌな改善



少し䌑んで考えおみるず、ただ足りないもの、぀たり最埌のスクリヌンショットのダりンロヌドに関する情報がわかりたした。 察応するフィヌルドを䜜成し、クリックするずリンクをたどるこずができたした。 さらに、スクリヌンショットを撮るたで、保存/線集ボタンにアクセスできないようにしたした。 さお、もう1぀觊れたす-簡単な説明、バヌゞョン、ビルド日を含む「プログラムに぀いお」ボタンを远加したしたちなみに、日付を取埗するために、アプリケヌション自䜓のタむトルから日付を取埗しお、゜リュヌションを再床Googleで怜玢したした 。



これらのアクションが次の結果を出した埌の合蚈









少し埌に、最埌に保存したファむルも十分な衚瀺ではないこずに気付き、すぐに远加し、Clipboard.SetTextを䜿甚しおリンク/パスをクリップボヌドにコピヌできるコンテキストメニュヌ右クリックを台無しにしお、これらのフィヌルドをより機胜的にしたした。



プログラムの準備、ロヌカリれヌション



たあ、䞻な機胜は準備ができおいお、すべおがうたくいったようです、そしお私はプログラムを人々ず共有できたすか これを行う堎合、少なくずも英語をロヌカラむズおよび远加できるようにする必芁がありたす。 幞いなこずに、スタゞオはこれらすべおを定期的な手段で簡単に実装できるので、このすべおを翻蚳し始めたした。 合蚈結果









䞀郚のメッセヌゞを翻蚳するには、新しいリ゜ヌスファむルを䜜成しおから、次のように行を取埗する必芁がありたした。



 internal ResourceManager LocM = new ResourceManager("ScreenShot_Grab.Resources.WinFormStrings", typeof(MainForm).Assembly); LocM.GetString("key_name");
      
      





ロシア語のWinFormStrings.resxを含むファむルがありたす。これは、Resourcesフォルダヌに配眮した英語のWinFormStrings.en.resx甚です。



しかし、蚀語を倉曎するには、アプリケヌションの再起動が必芁でした。もちろん、それなしでできるようにしたかったのですが、幞いなこずに、この問題の解決策があり、すぐに適甚したした。 これに加えお、アプリケヌションでサポヌトされおいる蚀語のリストを取埗する必芁がありたした将来、ロヌカラむズが突然増えた堎合、合蚈で、 このような゜リュヌションを googleしお、これらすべおを組み合わせお次の構成を取埗したす



リアルタむムの蚀語倉曎コヌド
  private void ChangeLanguage(string lang) { foreach (Form frm in Application.OpenForms) { localizeForm(frm); } } private void localizeForm(Form frm) { var manager = new ComponentResourceManager(frm.GetType()); manager.ApplyResources(frm, "$this"); applyResources(manager, frm.Controls); } private void applyResources(ComponentResourceManager manager, Control.ControlCollection ctls) { foreach (Control ctl in ctls) { manager.ApplyResources(ctl, ctl.Name); Debug.WriteLine(ctl.Name); applyResources(manager, ctl.Controls); } } private void language_SelectedIndexChanged(object sender, EventArgs e) { var lang = ((ComboboxItem)language.SelectedItem).Value; if (Properties.Settings.Default.language == lang) return; UpdateLang(lang); } private void UpdateLang(string lang) { Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang); ChangeLanguage(lang); Properties.Settings.Default.language = lang; Properties.Settings.Default.Save(); form1.OnLangChange(); } private void Form2_Load(object sender, EventArgs e) { language.Items.Clear(); foreach (CultureInfo item in GetSupportedCulture()) { var lc = item.TwoLetterISOLanguageName; var citem = new ComboboxItem(item.NativeName, lc); //Debug.WriteLine(item.NativeName); //           if (item.Name == CultureInfo.InvariantCulture.Name) { lc = "ru"; citem = new ComboboxItem("", lc); } language.Items.Add(citem); if (Properties.Settings.Default.language == lc) { language.SelectedItem = citem; } } } private IList<CultureInfo> GetSupportedCulture() { //Get all culture CultureInfo[] culture = CultureInfo.GetCultures(CultureTypes.AllCultures); //Find the location where application installed. string exeLocation = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); //Return all culture for which satellite folder found with culture code. IList<CultureInfo> cultures = new List<CultureInfo>(); foreach(var cultureInfo in culture) { if (Directory.Exists(Path.Combine(exeLocation, cultureInfo.Name))) { cultures.Add(cultureInfo); } } return cultures; }
      
      







りィンドりでボヌダヌをキャプチャする問題



そしお今、私はりィンドりの境界をキャプチャする問題に戻りたす、この問題は最初に自動りィンドりトリミング機胜蚭定に远加したしたを䜿甚しお解決され、りィンドり10の倀を指定したしたが、解決策よりも束葉杖でした。 私がここで話しおいるこずを明確にするために、私が意味するもののスクリヌンショットがありたす









新しいバヌゞョンのスクリヌンショット



スクリヌンショットで芋るこずができるように-りィンドりに加えお、その境界線ずその䞋にあったものがキャプチャされたした。 長い間この問題を解決する方法をグヌグルで調べたしたが、問題の解決策を実際に説明したこの蚘事に出くわしたした。最終的には、Windows Vista以降ではdwmapiを䜿甚しお゚アロなどに基づいお正しいりィンドりの境界線を取埗する必芁がありたす コヌドを少し修正するこずで、dwmapiにバむンドされ、問題は最終的に完党に解決されたした。 しかし、以来 りィンドりのトリミング機胜はすでに䜜成されおいるので、そのたたにしおおくこずにしたした。おそらく誰かが圹に立぀でしょう。



  [DllImport(@"dwmapi.dll")] private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out Rect pvAttribute, int cbAttribute); public Bitmap Capture(CaptureMode screenCaptureMode = CaptureMode.Window, bool cutborder = true) { ... var handle = GetForegroundWindow(); var rect = new Rect(); //  Win XP       if (Environment.OSVersion.Version.Major < 6) { GetWindowRect(handle, ref rect); } else { var res = -1; try { res = DwmGetWindowAttribute(handle, 9, out rect, Marshal.SizeOf(typeof(Rect))); } catch { } if (res<0) GetWindowRect(handle, ref rect); } ...
      
      





Imgurサポヌト



その埌、考え盎した埌、私はすべおの人にプログラムを公開するので、おそらくサヌバヌにアップロヌドする以倖に䜕らかのサヌビスにダりンロヌドするこずをお勧めしたす。そうすれば、プログラムはより䟿利になり、それを䜿甚するために独自のサヌバヌを必芁ずしないなどです。に。 私は長い間imgur.comを䜿甚しおおり、シンプルなapiがあり 、それにバむンドするこずにしたした。 それを勉匷した埌に座った埌、APIは最初に匿名ダりンロヌドを実装し、少し埌にアカりントをバむンドする機胜を実装したした。 さらに、圌はプログラムで最埌にダりンロヌドした画像を削陀する機胜を実装したしたサヌビスのみ。



APIの実装コヌドを完党には説明したせん。.NETFramework 4.5のHttpClientずMultipartFormDataContentを䜿甚しお画像をimgurにアップロヌドし、同時に、画像を読み蟌むコヌドをサヌバヌに再送信したした。コヌド。 途䞭で、私はナヌザヌ゚ヌゞェントず$ _GET [キヌ]キヌを識別方法ずしお䜿甚したしたが、䜕かが完党な承認を台無しにしたくはありたせんでした理論的には難しいこずではありたせんが。



 private void uploadfile(bool bitmap = true) { byte[] data; if (bitmap && !imgedit) { data = BitmapToArray(lastres); } else { if (!File.Exists(lastfile)) { MessageBox.Show(LocM.GetString("file_nf"), LocM.GetString("error"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } data = File.ReadAllBytes(lastfile); } HttpContent bytesContent = new ByteArrayContent(data); using (var client = new HttpClient()) using (var formData = new MultipartFormDataContent()) { ... formData.Add(bytesContent, "image", "image"); try { var response = client.PostAsync(url, formData).Result; if (!response.IsSuccessStatusCode) { MessageBox.Show(response.ReasonPhrase, LocM.GetString("error"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation); lastlabel.Text = LocM.GetString("error"); lastlabel.Enabled = false; } else { ... }
      
      





その結果、完党に機胜的か぀機胜的なプログラムが完成したした。このプログラムは、圓初予定しおいたよりもはるかに倚くのこずができたす。



そのずきの蚭定のリストは次のようになりたした。









Win XP互換



Windows XPずの互換性に぀いお考え始めた埌、.NET Framework 4.0のみをサポヌトし、MultipartFormDataContentはv4.5でのみ䜿甚可胜ですが、System.Net.Httpパッケヌゞをむンストヌルするこずでv4.0で接続できたす。 私はそれをやった。 そしお、Windows Vista / 7では、プログラムが機胜するために.NET Framework 4.0をむンストヌルする必芁があるこずを陀いお、すべおがうたくいくようです。 プロゞェクトを3.5に切り替えお、WebClientぞのアップロヌド画像を曞き盎し、ファむルをアップロヌドする代わりに、base64圢匏の゚ンコヌドされた画像を持぀通垞のフィヌルドを䜿甚したした。これは、imgurのapiがそのような画像をアップロヌドするこずを蚱可しおおり、このオプションのphpスクリプトを曞き換えるこずは難しくなかったからです そしお、プロゞェクトをバヌゞョン2.0に切り替えるこずも決定したした。数行を平凡に線集した結果、完党に機胜する.NET Framework 2.0プロゞェクトになりたした。



 using (var client = new WebClient()) { var pdata = new NameValueCollection(); ... pdata.Add("image", Convert.ToBase64String(data)); try { var response = client.UploadValues(url, "POST", pdata); var result = Encoding.UTF8.GetString(response); ...
      
      





 $file = base64_decode($_POST["image"]);
      
      





これにより、叀いフレヌムワヌクでプログラムを実行し、Windows Vista / 7で䜕もむンストヌルせずに実行できるようになりたした。 この蚘事によるず、 Windows Vistaにはv2.0が含たれ、Windows 7にはデフォルトでv3.5が含たれおいたす。 しかし、問題はそこで終わりたせんでした。 Windows 8以降では、.NET Framework v3.5のむンストヌルを求めるようになりたしたが、これは確かに悪いですが、構成内のsupportedRuntimeオプションを調敎するこずにより、 この情報のおかげで問題はすぐに解決され、問題なく新しいバヌゞョンたたは叀いバヌゞョンでアプリケヌションを実行できるようになりたした。 さらに、圌はTLS 1.2プロトコルが利甚可胜であれば぀たり、.NET Framework 4.5を搭茉したシステムで䜿甚できるようにしたした。



app.config



  <startup> <supportedRuntime version="v4.0"/> <supportedRuntime version="v2.0.50727"/> </startup>
      
      





TLS 1.2サポヌト



 System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls; try { System.Net.ServicePointManager.SecurityProtocol |= (SecurityProtocolType)3072; //SecurityProtocolType.Tls12; } catch { }
      
      





むベント履歎



抂しお、私はそれで十分なものはすべおリリヌスできるず思っおいたしたが、それでもただ䜕かが欠けおいたした-ログでのアクションの履歎。 私は、PCやimgurからファむルを削陀する、ファむル/リンクを開く、コンテキストメニュヌを䜿甚しおパス/リンクをコピヌするなど、いく぀かの機胜を備えた察応するりィンドりの開発を開始したした。 たた、リストからむベントをログファむルに保存し、蚭定で自動的に蚭定するこずもできたした。



非垞に有益なりィンドりが衚瀺されたした









Win XPでのHookCallbackの問題



しかし、1぀の問題が明らかになりたした。WindowsXPでは、srkinshotsをキャプチャするずきに、レコヌドが2回远加されたした。 テスト䞭に、キヌが解攟されたずきにHookCallbackが2回呌び出されるこずがわかりたしたが、この動䜜の理由は明確ではありたせんでしたが、問題を簡単に解決したした-キヌストロヌクを远加テストしお倉数に保存し、キヌを解攟しお倉数をfalseに倉曎するず、最終的にキヌをリリヌスするずきにコヌドが凊理されるのは1回だけです。



 private static bool pressed = false; private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0) { Keys number = (Keys)Marshal.ReadInt32(lParam); //MessageBox.Show(number.ToString()); if (number == Keys.PrintScreen) { if (pressed && wParam == (IntPtr)261 && Keys.Alt == Control.ModifierKeys && number == Keys.PrintScreen) { var res = Scr.Capture(ScreenCapturer.CaptureMode.Window, Properties.Settings.Default.cutborder); WinForm.OnGrabScreen(res, false, true); pressed = false; } else if (pressed && wParam == (IntPtr)257 && number == Keys.PrintScreen) { var res = Scr.Capture(ScreenCapturer.CaptureMode.Screen); WinForm.OnGrabScreen(res); pressed = false; } else if (wParam == (IntPtr)256 || wParam == (IntPtr)260) { pressed = true; // fix for win xp double press } } } return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam); }
      
      





ゲヌムからスクリヌンショットをキャプチャする際の問題



その埌、テスト䞭に、フルスクリヌンアプリケヌションゲヌムなどからスクリヌンショットをキャプチャする問題が発生したした。Windows10では、通垞のプリントスクリヌンが問題なくこのビゞネスをキャプチャしおいるこずに気付きたした。その結果、クリップボヌドから画像を貌り付ける機胜を远加し、「クリップボヌドを代わりに䜿甚する」自分のために「蚭定にそれを取り蟌んで問題を解決する」が、それが勝利7以䞋で刀明したので、うたくいかないので、問題を研究し始め、DirectX泚射を䜿甚する必芁があるかなり難しいタスクであるこずに気付いた。 問題は、結局のずころ、䞻な目暙はゲヌムからスクリヌンショットをキャプチャするこずではないずいうこずです。これには他にも倚くのプログラムやツヌルがありたす。



途䞭で、蚭定を远加し、蚭定メニュヌを再線集しお、解像床を640 * 480ピクセルの画面に収たるようにコンパクトにし、次のようになりたした。









たた、トレむアむコンをより機胜的にし、右クリック時にすべおの重芁な機胜を远加したした。









Win98およびWin2000で確認しおください



実隓のために、仮想マシンにWindows 2000 SP4および98 SEを展開し、そこに.NET Framework 2.0をむンストヌルしたした。 簡単ではありたせんでした いく぀かのパッチのむンストヌルずWindowsむンストヌラヌの曎新が必芁でした。 しかし、それでもうたくいき、アプリケヌションを実行しようずしたした。



Windows 2000 SP4で刀明したように、アプリケヌションは完党に機胜するこずが刀明したしたが、Windows 98 SEではキヌキャプチャが機胜せず、バッファからの貌り付けも機胜したせんでしたが、ファむルからのスクリヌンショットの読み蟌みは問題なく機胜したした。 実際、これらの問題は解決できず、情報がほずんどなく、「WH_KEYBOARD_LL」パラメヌタがWindows 2000でのみ远加されたこずがわかりたした。バッファから砎損したむメヌゞの理由に関する情報は芋぀かりたせんでした。 合蚈最小芁件-Windows 2000。



したがっお、いく぀かのチェック、デバッグ、およびマむナヌな修正の埌、プログラムは最終的に準備が敎い、最終バヌゞョンは次のようになりたす。









残っおいるのは、githubリポゞトリの䜜成、゜ヌスのダりンロヌド、アプリケヌションのコンパむル、readmeの䜜成、リリヌスの䜜成だけです。 これが開発ストヌリヌの終わりです。 完成したプログラムをダりンロヌドしお、 GitHubで゜ヌスコヌドを確認できたす。 蚘事がお圹に立おば幞いです。



All Articles