'Print screen' scrollowanego okna

'Print screen' scrollowanego okna
JS
  • Rejestracja:prawie 12 lat
  • Ostatnio:ponad 11 lat
  • Postów:17
0

Witam,

potrzebuję zrobić program działający w podobny sposób, jak np FastStone capture: mamy scrollowane okno, np w notatniku albo przeglądarce i program wyrzuca nam obrazek z zawartością tego okna. O ile z robieniem i łączeniem screenów nie powinienem mieć problemów, o tyle ze scrollowaniem nie mogę sobie poradzić. Bazując na paru skryptach z netu napisałem coś takiego:

Kopiuj
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;
using System.Threading;

namespace scroller
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetScrollPos(IntPtr hWnd, int nBar);

        [DllImport("user32.dll")]
        static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);

        [DllImport("user32.dll")]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
            
        [DllImport("user32.dll")]
        static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    
        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
    
        [DllImport("user32.dll")]
        static extern IntPtr SetActiveWindow(IntPtr hWnd);
    
        [DllImport("user32.dll", SetLastError = true)]
        static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
        static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

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

        [DllImport("user32.dll")]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

        internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);

        [DllImport("user32.dll")]
        internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);


        private void Form1_Load(object sender, EventArgs e)
        {

            List<IntPtr> result = new List<IntPtr>();

            Thread.Sleep(5000);
            
            IntPtr ParenthWnd = GetForegroundWindow();
            if (!ParenthWnd.Equals(IntPtr.Zero))
            {
                StringBuilder myStringBuilder = new StringBuilder(256);
                GetWindowText(ParenthWnd, myStringBuilder, 256);
                this.Text = myStringBuilder.ToString();

                IntPtr prevChild = IntPtr.Zero;
                IntPtr currChild = IntPtr.Zero;
                while (true)
                {
                    currChild = FindWindowEx(ParenthWnd, prevChild, null, null);
                    if (currChild == IntPtr.Zero) break;
                    result.Add(currChild);
                    prevChild = currChild;
                }
            }
            for(int i=0 ;i<=result.Count-1;i++){
            IntPtr myHandle = result[i];
            SetActiveWindow(ParenthWnd);
            SwitchToThisWindow(myHandle, true);
            SetScrollPos(myHandle, 0x1, 0, true);
            PostMessage(myHandle, 0x115, 4 + 0x10000 * 0,0);
            }

        }        
    }
}

Ten kod ma za zadanie przesunąć pionowego scrolla do pozycji 0. Ma to działać w ten sposób, że odpalamy aplikacje, mamy 5 sekund na wybranie programu z naszym oknem, a ona znajduje wszystkie 'podokna' tego programu i przesuwa ich pionowe scrolle na samą górę. Niestety, o ile np w notatniku i notepadzie++ wszystko działa jak należy, o tyle np w przeglądarkach czy w w wordzie nic się nie dzieje.

Będe wdzięczny za pomoc w rozwiązaniu problemu

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 22 godziny
0

Może aplikacja nie ma standardowego scrolla, tylko symulowany, który nie odpowiada na komunikaty.

JS
czyli najlepszym rozwiązaniem jest wysyłanie keystroke'ów?
JS
  • Rejestracja:prawie 12 lat
  • Ostatnio:ponad 11 lat
  • Postów:17
0

mój problem został częściowo rozwiązany poprzez użycie SendKeys:

Kopiuj
SendKeys.SendWait("{DOWN}")

jednak pojawia się nowy aspekt: jak połączyć zrobione screeny, skoro nie wiem, o ile px każdy jest wobec poprzedniego przesunięty? jakieś pomysły?

edit: dobra, trzeba mu wysłać ctrl+pageDown

edytowany 2x, ostatnio: John Smith
JS
  • Rejestracja:prawie 12 lat
  • Ostatnio:ponad 11 lat
  • Postów:17
0

jeszcze jeden problem. scrolluje sobie okno, robię screeny, ale kiedy skończyć? jak wykryć, że scroll zjechał już na sam dół?

jedynym sposobem jaki przychodzi mi na myśl jest porównywanie danego i poprzedniego screena, ale to będzie raczej mało wydajne wyjście z sytuacji...

edytowany 1x, ostatnio: John Smith

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.