dhq_boiler
@dhq_boiler

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Ajaxでimg要素を部分更新したい

解決したいこと

WinDesktopAppOnCloudというプロジェクトで、ブラウザ上で.NET デスクトップアプリ(WPFやWin Forms)をデバッグするシステムを開発しようとしています。正直言って実現できるかどうかわかりませんが、挑戦してみるつもりです。

今、Index.cshtmlのimg要素(id="appFace")のsrc属性に@ViewData["ImgSrc"]を入れました。

Index.cshtml(後半)
(略)
<div class="text-center">
    <form id="main" method="post">
        @Html.AntiForgeryToken()
        <a href="" data-ajax="true" data-ajax-url="/" data-ajax-update="#panel">Click here</a>
        <div id="panel">
            <img id="appFace" src='@ViewData["ImgSrc"]' />
        </div>
    </form>
</div>

この要素を部分更新するにはAjaxを使うべきということは理解しているのですが、javascriptのコードを書いてみたところ正しく動作していないようです。

Index.cshtml(前半)
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<script type="text/javascript">
    window.onload = function () {
        $('#appFace').on('click', function (e) {
            console.log("click success");
        });
        $('#appFace').on('mousemove', function (e) {
            var mX = e.offsetX;
            var mY = e.offsetY;
            $.ajax({
                type: "POST",
                url: "/?handler=MouseMove",
                cache: false,
                dataType: "json",
                data: { x: mX, y: mY },
                async: false,
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                },
                success: function (data) {
                    console.log("MouseMove success");
                },
                error: function (jqxhr, status, exception) {
                    console.debug('jqxhr', jqxhr);
                    console.debug('status', status);
                    console.debug('exception', exception);
                }
            });
        });
        $('#appFace').hover(
            function (e) {
                $.ajax({
                    type: "POST",
                    url: "/?handler=SetCapture",
                    cache: false,
                    dataType: "json",
                    data: { },
                    async: false,
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                    },
                    success: function (data) {
                        console.log("SetCapture success");
                    }
                });
            },
            function (e) {
                $.ajax({
                    type: "POST",
                    url: "/?handler=ReleaseCapture",
                    cache: false,
                    dataType: "json",
                    data: { },
                    async: false,
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                    },
                    success: function (data) {
                        console.log("ReleaseCapture success");
                    }
                });
            }
        );
    }
</script>

Chromeの開発ツールを確認すると、コンソールにデバッグログが出力されていました。

2021-12-07 (1).png

どうすれば$.ajax()を完遂することができますか?
また$.ajax()を完遂すれば、img要素の部分更新が実現できるでしょうか?実現するにはまだ追加のコードが必要ですか?

Index.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace WinDesktopAppOnCloud.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;
        private Process _process;

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }

        private bool PrevInstance()
        {
            var processes = Process.GetProcessesByName("boilersGraphics");
            if (processes.Length >= 1)
                return true;
            else
                return false;
        }

        public void OnGet()
        {
            StartDesktopAppProcessAndPrintScreen();
        }

        private void StartDesktopAppProcessAndPrintScreen()
        {
            StartDesktopAppProcess();

            PrintScreen();
        }

        private void StartDesktopAppProcess()
        {
            if (PrevInstance() == false)
            {
                var app = new ProcessStartInfo();
                app.FileName = @"Z:\Git\boilersGraphics\boilersGraphics\bin\Debug\boilersGraphics.exe"; //将来的にはビルドシステムも搭載して、GitHubからソースコードをクローンして自鯖でビルドしてオンラインデバッグできるようにする
                _process = Process.Start(app);
                Thread.Sleep(1000);
            }
        }

        private void PrintScreen()
        {
            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            IntPtr hWnd = _process.MainWindowHandle;
            while (hWnd == IntPtr.Zero)
            {
                _process.Refresh();
                hWnd = _process.MainWindowHandle;
            }
            IntPtr winDC = GetWindowDC(hWnd);
            //ウィンドウの大きさを取得
            RECT winRect = new RECT();
            GetWindowRect(hWnd, ref winRect);
            //Bitmapの作成
            Bitmap bmp = new Bitmap(winRect.right - winRect.left,
                winRect.bottom - winRect.top);
            //Graphicsの作成
            Graphics g = Graphics.FromImage(bmp);
            //Graphicsのデバイスコンテキストを取得
            IntPtr hDC = g.GetHdc();

            PrintWindow(hWnd, hDC, 0);
            //Bitmapに画像をコピーする
            BitBlt(hDC, 0, 0, bmp.Width, bmp.Height,
                winDC, 0, 0, SRCCOPY);
            //解放
            g.ReleaseHdc(hDC);
            g.Dispose();
            ReleaseDC(hWnd, winDC);

            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, ImageFormat.Jpeg);
            var array = ms.ToArray();
            ms.Close();

            ViewData["ImgSrc"] = String.Format("data:image/jpeg;base64,{0}", Convert.ToBase64String(array));
        }

        private byte[] PrintScreenAsByteArray()
        {
            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            IntPtr hWnd = _process.MainWindowHandle;
            while (hWnd == IntPtr.Zero)
            {
                _process.Refresh();
                hWnd = _process.MainWindowHandle;
            }
            IntPtr winDC = GetWindowDC(hWnd);
            //ウィンドウの大きさを取得
            RECT winRect = new RECT();
            GetWindowRect(hWnd, ref winRect);
            //Bitmapの作成
            Bitmap bmp = new Bitmap(winRect.right - winRect.left,
                winRect.bottom - winRect.top);
            //Graphicsの作成
            Graphics g = Graphics.FromImage(bmp);
            //Graphicsのデバイスコンテキストを取得
            IntPtr hDC = g.GetHdc();

            PrintWindow(hWnd, hDC, 0);
            //Bitmapに画像をコピーする
            BitBlt(hDC, 0, 0, bmp.Width, bmp.Height,
                winDC, 0, 0, SRCCOPY);
            //解放
            g.ReleaseHdc(hDC);
            g.Dispose();
            ReleaseDC(hWnd, winDC);

            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, ImageFormat.Jpeg);
            var array = ms.ToArray();
            ms.Close();

            return array;
        }

        public void OnPostMouseMove()
        {
            StartDesktopAppProcess();

            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            //SendMessageでマウスポインタが移動したことをDesktopApp側に伝える
            Trace.WriteLine($"SendMessage hWnd={_process.MainWindowHandle}, Msg={WM_MOUSEMOVE}, wParam={0x0}, lParam={JsonToPoint()}");
            SendMessage(_process.MainWindowHandle, WM_MOUSEMOVE, 0x0, new IntPtr(PointToParam(JsonToPoint())));
            PrintScreen();
        }

        public void OnPostSetCapture()
        {
            StartDesktopAppProcess();

            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            //Trace.WriteLine("SetCapture");

            SetCapture(_process.MainWindowHandle);
        }

        public ActionResult ShowImage()
        {
            return File(PrintScreenAsByteArray(), "image/jpeg");
        }

        public void OnPostReleaseCapture()
        {
            //Trace.WriteLine("ReleaseCapture");

            ReleaseCapture();
        }

        private int PointToParam(Point point)
        {
            return (int)point.X << 16 | (int)point.Y;
        }

        private Point JsonToPoint()
        {
            StreamReader reader = new StreamReader(Response.Body);
            Response.Body.Seek(0, SeekOrigin.Begin);
            string str = reader.ReadToEnd();
            var dict = HttpUtility.ParseQueryString(str);
            var point = new Point();
            point.X = int.Parse(dict["x"]);
            point.Y = int.Parse(dict["y"]);
            return point;
        }

        private const int SRCCOPY = 13369376;
        private const int CAPTUREBLT = 1073741824;

        [DllImport("user32.dll")]
        private static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("gdi32.dll")]
        private static extern int BitBlt(IntPtr hDestDC,
            int x,
            int y,
            int nWidth,
            int nHeight,
            IntPtr hSrcDC,
            int xSrc,
            int ySrc,
            int dwRop);

        [DllImport("user32.dll")]
        private static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);


        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowDC(IntPtr hwnd);

        //[DllImport("user32.dll")]
        //private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern int GetWindowRect(IntPtr hwnd,
            ref RECT lpRect);

        [DllImport("User32.dll")]
        private extern static bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);

        //送信するためのメソッド(文字も可能)
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool PostMessage(IntPtr hWnd, IntPtr wMsg, IntPtr wParam, ref IntPtr lParam);

        [DllImport("user32.dll")]
        static extern IntPtr SetCapture(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern bool ReleaseCapture();

        public const int WM_MOUSEMOVE = 0x0200;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_LBUTTONUP = 0x202;
        public const int MK_LBUTTON = 0x0001;
    }
}

該当するソースコード

注意

当プロジェクトは現状デバッグ対象のアプリとして、boiler's Graphicsのバイナリに依存しており、boiler's Graphicsをビルドしておかないと上手く実行されません。
お手数ですが以下からコードをクローンすることをお試し下さい。

よろしくお願いいたします。

0

6Answer

レスポンスとして {"src": "data:image/jpeg;..."} を返し、

という部分がよくわからなかったのですが、
レスポンスに"src":"data:image/jpeg;..."の組を含めるにはどうしたら良いでしょうか?

レスポンスヘッダに Content-Type: application/json をセットし、レスポンスボディとして JSON 文字列 {"src": "data:image/jpeg;..."} を返すという意味です。 ASP.NET Core には詳しくありませんがこんな感じで動くと思います。

public IActionResult OnPostMouseMove()
{
    // 略

    var src = ...;
    var data = new Dictionary<string, string>() { {"src", src} };
    return new JsonResult(data);
}

そもそもこの方法だと、F5更新されるまで@ViewData["ImgSrc"]の値が更新されないのでは?
と思いました。

私の回答は以下の流れを実装する想定です:

  • まずブラウザで Index ページを表示する。
  • ブラウザはユーザが img 要素の上でマウスを動かすたびに POST /?handler=MouseMove リクエストを送る。
    • (コードに onmouseover ハンドラが書かれていたからそうしただけで、リクエストを送るタイミングや送信先アクションはこの通りでなくても構いません。)
  • サーバはリクエストに対して新しい画像データを含む JSON 文字列を返す。
  • ブラウザは返ってきた JSON 文字列から画像データを取り出し img 要素の src にセットする。

よって、 F5 で更新しなくても任意のタイミングで画像だけ更新することができます。

1Like

POST /?handler=MouseMove をリクエストする Ajax において、レスポンスに JSON を期待するところ HTML が返ってきてパースエラーが出ています。これはログのスクリーンショットの真ん中あたりに responseText: "x=464&y=363<!DOCTYPE ... と出ていることから分かります。(以前の質問にあった謎のログ x=464&y=363 が出ていて HTML としても壊れていますね。)

レスポンスとして {"src": "data:image/jpeg;..."} を返し、以下のように img 要素の src 属性をセットすれば画像を差し替えられます。

success: function (data) {
  $("#appFace").attr("src", data.src);
}
0Like

レスポンスとして {"src": "data:image/jpeg;..."} を返し、

という部分がよくわからなかったのですが、
レスポンスに"src":"data:image/jpeg;..."の組を含めるにはどうしたら良いでしょうか?

以下のように試しに書いてみましたが、これだとajaxで500が出ます。

Index.cshtml.cs
        public IActionResult OnPostMouseMove()
        {
            StartDesktopAppProcess();

            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            //SendMessageでマウスポインタが移動したことをDesktopApp側に伝える
            Trace.WriteLine($"SendMessage hWnd={_process.MainWindowHandle}, Msg={WM_MOUSEMOVE}, wParam={0x0}, lParam={JsonToPoint()}");
            SendMessage(_process.MainWindowHandle, WM_MOUSEMOVE, 0x0, new IntPtr(PointToParam(JsonToPoint())));
            PrintScreen();
            var viewData = new ViewDataDictionary(this.ViewData);
            viewData.Add(new KeyValuePair<string, object>("src", ViewData["ImgSrc"]));
            return new ViewResult() { ViewData = viewData };
        }

2021-12-08.png

あと、以下のコードも試しましたが、ダメでした。

Index.cshtml.cs
        public void OnPostMouseMove()
        {
            StartDesktopAppProcess();

            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            //SendMessageでマウスポインタが移動したことをDesktopApp側に伝える
            Trace.WriteLine($"SendMessage hWnd={_process.MainWindowHandle}, Msg={WM_MOUSEMOVE}, wParam={0x0}, lParam={JsonToPoint()}");
            SendMessage(_process.MainWindowHandle, WM_MOUSEMOVE, 0x0, new IntPtr(PointToParam(JsonToPoint())));
            PrintScreen();

            ViewData["src"] = ViewData["ImgSrc"]; //ViewData["ImgSrc"]に"data:image/jpeg;base64,..."が入る
        }

2021-12-08 (1).png

0Like

あとこのコードも試しました。
dataにsrc:"@ViewData["ImgSrc"]"を含めてみました。
しかしこれもダメでしたね。

Index.cshtml
           $.ajax({
                type: "POST",
                url: "/?handler=MouseMove",
                cache: false,
                dataType: "json",
                data: { x: mX, y: mY, src: "@ViewData["ImgSrc"]" },
                async: false,
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                },
                success: function (data) {
                    $("#appFace").attr("src", data.src);
                },
                error: function (jqxhr, status, exception) {
                    console.debug('jqxhr', jqxhr);
                    console.debug('status', status);
                    console.debug('exception', exception);
                }
            });

2021-12-08 (2).png

そもそもこの方法だと、F5更新されるまで@ViewData["ImgSrc"]の値が更新されないのでは?
と思いました。

0Like

とりあえず、img画像の更新はできました。
ホントはSendMessage()でWM_MOUSEMOVEを指定すればリモートでポインタの位置を更新できるかなと思っていましたが、これは奥が深いようです。

mousemove_demo.gif

上記の画像はアプリ本物を動かすと座標が変わるのを確認して、偽物の方で動かすと一瞬反映されるが継続的に座標が変わらない問題は健在。

@uasi さん回答していただきありがとうございました。

0Like

Comments

  1. @dhq_boiler

    Questioner

    コミットするのを忘れた可能性がある。
    寝て起きたら、コード全文貼りますね。

一部のソースコードを貼ります。

Index.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace WinDesktopAppOnCloud.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;
        private Process _process;

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }

        private bool PrevInstance()
        {
            var processes = Process.GetProcessesByName("boilersGraphics");
            if (processes.Length >= 1)
                return true;
            else
                return false;
        }

        public void OnGet()
        {
            StartDesktopAppProcessAndPrintScreen();
        }

        private void StartDesktopAppProcessAndPrintScreen()
        {
            StartDesktopAppProcess();

            PrintScreen();
        }

        private void StartDesktopAppProcess()
        {
            if (PrevInstance() == false)
            {
                var app = new ProcessStartInfo();
                app.FileName = @"Z:\Git\boilersGraphics\boilersGraphics\bin\Debug\boilersGraphics.exe"; //将来的にはビルドシステムも搭載して、GitHubからソースコードをクローンして自鯖でビルドしてオンラインデバッグできるようにする
                _process = Process.Start(app);
                Thread.Sleep(1000);
            }
        }

        private void PrintScreen()
        {
            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            IntPtr hWnd = _process.MainWindowHandle;
            while (hWnd == IntPtr.Zero)
            {
                _process.Refresh();
                hWnd = _process.MainWindowHandle;
            }
            IntPtr winDC = GetWindowDC(hWnd);
            //ウィンドウの大きさを取得
            RECT winRect = new RECT();
            GetWindowRect(hWnd, ref winRect);
            //Bitmapの作成
            Bitmap bmp = new Bitmap(winRect.right - winRect.left,
                winRect.bottom - winRect.top);
            //Graphicsの作成
            Graphics g = Graphics.FromImage(bmp);
            //Graphicsのデバイスコンテキストを取得
            IntPtr hDC = g.GetHdc();

            PrintWindow(hWnd, hDC, 0);
            //Bitmapに画像をコピーする
            BitBlt(hDC, 0, 0, bmp.Width, bmp.Height,
                winDC, 0, 0, SRCCOPY);
            //解放
            g.ReleaseHdc(hDC);
            g.Dispose();
            ReleaseDC(hWnd, winDC);

            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, ImageFormat.Jpeg);
            var array = ms.ToArray();
            ms.Close();

            ViewData["ImgSrc"] = String.Format("data:image/jpeg;base64,{0}", Convert.ToBase64String(array));
        }

        private byte[] PrintScreenAsByteArray()
        {
            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            IntPtr hWnd = _process.MainWindowHandle;
            while (hWnd == IntPtr.Zero)
            {
                _process.Refresh();
                hWnd = _process.MainWindowHandle;
            }
            IntPtr winDC = GetWindowDC(hWnd);
            //ウィンドウの大きさを取得
            RECT winRect = new RECT();
            GetWindowRect(hWnd, ref winRect);
            //Bitmapの作成
            Bitmap bmp = new Bitmap(winRect.right - winRect.left,
                winRect.bottom - winRect.top);
            //Graphicsの作成
            Graphics g = Graphics.FromImage(bmp);
            //Graphicsのデバイスコンテキストを取得
            IntPtr hDC = g.GetHdc();

            PrintWindow(hWnd, hDC, 0);
            //Bitmapに画像をコピーする
            BitBlt(hDC, 0, 0, bmp.Width, bmp.Height,
                winDC, 0, 0, SRCCOPY);
            //解放
            g.ReleaseHdc(hDC);
            g.Dispose();
            ReleaseDC(hWnd, winDC);

            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, ImageFormat.Jpeg);
            var array = ms.ToArray();
            ms.Close();

            return array;
        }

        public IActionResult OnPostSetPoint(int x, int y)
        {
            var data = new Dictionary<string, string>() { { "x", x.ToString() }, { "y", y.ToString() } };
            //var point = new Point();
            //point.X = x;
            //point.Y = y;
            //ViewData["point"] = point;
            return new JsonResult(data);
        }

        public IActionResult OnPostMouseMove(int x, int y)
        {
            StartDesktopAppProcess();

            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }
            var point = new Point(x, y);
            //SendMessageでマウスポインタが移動したことをDesktopApp側に伝える
            Trace.WriteLine($"SendMessage hWnd={_process.MainWindowHandle}, Msg={WM_MOUSEMOVE}, wParam={0x0}, lParam={point}");
            SendMessage(_process.MainWindowHandle, WM_MOUSEHOVER, 0x0000, new IntPtr(PointToParam(point)));
            //PostMessage(new HandleRef(null, _process.MainWindowHandle), WM_MOUSEMOVE, (IntPtr)0, (IntPtr)PointToParam(point));
            ShowIfError();
            
            PrintScreen();
            var data = new Dictionary<string, string>() { { "src", ViewData["ImgSrc"].ToString() } };
            return new JsonResult(data);
        }

        public void OnPostSetCapture()
        {
            StartDesktopAppProcess();

            if (_process == null)
            {
                _process = Process.GetProcessesByName("boilersGraphics").First();
            }

            //Trace.WriteLine("SetCapture");

            SetCapture(_process.MainWindowHandle);
        }

        public ActionResult ShowImage()
        {
            return File(PrintScreenAsByteArray(), "image/jpeg");
        }

        public void OnPostReleaseCapture()
        {
            //Trace.WriteLine("ReleaseCapture");

            ReleaseCapture();
        }

        public void OnPostShutDown()
        {
            if (_process != null)
                _process.Kill();
        }

        private int PointToParam(Point point)
        {
            return (int)point.Y << 16 | (int)point.X & 0xFFFF;
        }

        private void ShowIfError()
        {
            var errorCode = Marshal.GetLastWin32Error();
            if (errorCode != 0)
            {
                StringBuilder message = new StringBuilder(255);
                FormatMessage(
                  FORMAT_MESSAGE_FROM_SYSTEM,
                  IntPtr.Zero,
                  (uint)errorCode,
                  0,
                  message,
                  message.Capacity,
                  IntPtr.Zero);
                _logger.LogError(message.ToString());
            }
            else
            {
                StringBuilder message = new StringBuilder(255);
                FormatMessage(
                  FORMAT_MESSAGE_FROM_SYSTEM,
                  IntPtr.Zero,
                  (uint)errorCode,
                  0,
                  message,
                  message.Capacity,
                  IntPtr.Zero);
                _logger.LogInformation(message.ToString());
            }
        }

        [DllImport("kernel32.dll")]
        public static extern uint FormatMessage(uint dwFlags, IntPtr lpSource,
                                                uint dwMessageId, uint dwLanguageId,
                                                StringBuilder lpBuffer, int nSize,
                                                IntPtr Arguments);
        public const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;

        private const int SRCCOPY = 13369376;
        private const int CAPTUREBLT = 1073741824;

        [DllImport("user32.dll")]
        private static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("gdi32.dll")]
        private static extern int BitBlt(IntPtr hDestDC,
            int x,
            int y,
            int nWidth,
            int nHeight,
            IntPtr hSrcDC,
            int xSrc,
            int ySrc,
            int dwRop);

        [DllImport("user32.dll")]
        private static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);


        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowDC(IntPtr hwnd);

        //[DllImport("user32.dll")]
        //private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern int GetWindowRect(IntPtr hwnd,
            ref RECT lpRect);
        
        [DllImport("User32.dll")]
        private extern static bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);

        //送信するためのメソッド(文字も可能)
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true )]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        static extern IntPtr SetCapture(IntPtr hWnd);
        
        [DllImport("user32.dll")]
        static extern bool ReleaseCapture();

        public const int WM_MOUSEMOVE = 0x0200;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_LBUTTONUP = 0x202;
        public const int MK_LBUTTON = 0x0001;
        public const int WM_MOUSEHOVER = 0x02A1;
    }
}

Index.cshtml
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<script type="text/javascript">
    window.onload = function () {
        $('#appFace').on('click', function (e) {
            console.log("click success");
        });
        $('#appFace').on('mousemove', function (e) {
            var mX = e.offsetX;
            var mY = e.offsetY;
            $.ajax({
                type: "POST",
                url: "/?handler=SetPoint&x=" + mX + "&y=" + mY,
                cache: false,
                async: false,
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                },
                success: function (data) {
                    console.log(data);
                    console.log("SetPoint success");
                    $.ajax({
                        type: "POST",
                        url: "/?handler=MouseMove&x=" + mX + "&y=" + mY,
                        cache: false,
                        async: false,
                        beforeSend: function (xhr) {
                            xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                        },
                        success: function (data) {
                            $("#appFace").attr("src", data.src);
                            console.log("rendered");
                        },
                        error: function (jqxhr, status, exception) {
                            console.debug('jqxhr', jqxhr);
                            console.debug('status', status);
                            console.debug('exception', exception);
                        }
                    });
                },
                error: function (jqxhr, status, exception) {
                    console.debug('jqxhr', jqxhr);
                    console.debug('status', status);
                    console.debug('exception', exception);
                }
            });
            
        });
        $('#appFace').hover(
            function (e) {
                $.ajax({
                    type: "POST",
                    url: "/?handler=SetCapture",
                    cache: false,
                    dataType: "json",
                    data: {},
                    async: false,
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                    },
                    success: function (data) {
                        console.log("SetCapture success");
                    }
                });
            },
            function (e) {
                $.ajax({
                    type: "POST",
                    url: "/?handler=ReleaseCapture",
                    cache: false,
                    dataType: "json",
                    data: {},
                    async: false,
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                    },
                    success: function (data) {
                        console.log("ReleaseCapture success");
                    }
                });
            }
        );
    }
    //window.onbeforeunload = function () {
    //    return 'Are you sure you want to leave?';
    //}
    window.onunload = function () {
        $.ajax({
            type: "POST",
            url: "/?handler=ShutDown",
            cache: false,
            async: true,
            beforeSend: function (xhr) {
                xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
            },
            success: function (data) {
                console.log("ShutDown success");
            }
        });
        console.log("aa");
    }
</script>

<div class="text-center">
    <form id="main" method="post">
        @Html.AntiForgeryToken()
        <a href="" data-ajax="true" data-ajax-url="/" data-ajax-update="#panel">Click here</a>
        <div id="panel">
            <img id="appFace" src='@ViewData["ImgSrc"]' />
        </div>
    </form>
</div>

貼り付けてみた感じだと、なんだかところどころ無駄なコードがあるような気がする...。

0Like

Your answer might help someone💌