Jacek Matulewski 21 listopada 2016

Slides:



Advertisements
Podobne prezentacje
Programowanie Windows
Advertisements

Wstęp do strumieni danych
C++ wykład 9 ( ) Szablony.
C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Programowanie obiektowe
Jarosław Kuchta Komunikaty w Windows.
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Wskaźniki repetytorium Wskaźniki int Y = 1, X = 2; X = 5; int *p = &X; Y X p 4 4 p = &Y; *p = 4; 5.
Wzorce.
Język ANSI C Funkcje Wykład: Programowanie komputerów
Prowadzący: mgr inż. Elżbieta Majka
Programowanie w środowisku sieciowym
PROGRAMOWANIE STRUKTURALNE
Tworzenie i obsługa programów – przykład 3 uwagi cd. Wykorzystując różne klasy biblioteki języka Java należy pamiętać w jakim pakiecie się znajdują. Wszystkie.
formatowanie kodu źródłowego
Programowanie obiektowe w Javie
Nowa wersja C# Autor: Piotr Sobczak
Programowanie Lokalnych Aplikacji .NET
1 Dygresja: cztery płyty główne…. 2 Dygresja: osobliwości C /* cos o nieistniejacym typie Boolean */ /* oraz o operatorze przecinkowym */ #include int.
C++ wykład 2 ( ) Klasy i obiekty.
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Visual C++ Zastosowania Informatyki Wykład 6 Copyright, 2003 © Adam Czajka.
C# Windows Forms Zastosowania Informatyki Wykład 3
Podstawy C# Grupa .NET PO.
Podstawy programowania II Wykład 2: Biblioteka stdio.h Zachodniopomorska Szkoła Biznesu.
Programowanie w Środowisku Windows Common controls.
Programowanie urządzeń mobilnych – wykład IV
Programowanie w Środowisku Windows
Podstawy programowania II
Podstawy WINAPI - MessageBOX
Programowanie obiektowe III rok EiT
Programowanie Windows na przykładzie C# część 1
Programowanie obiektowe – zastosowanie języka Java SE
Programowanie w Środowisku Windows
JAVA c.d.. Instrukcji wyboru SWITCH używamy, jeśli chcemy w zależności od wartości pewnego wyrażenia wykonać jeden z kilku fragmentów kodu. Jest to w.
Andrzej Repak Nr albumu
Java – coś na temat Klas Piotr Rosik
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
C# Platforma .NET CZ.3 Kuba Ostrowski.
Podstawy informatyki 2013/2014
1 Strumienie Hierarchie klas strumieniowych, strumienie bajtowe - klasy InputStream i OutputStream i ich metody, klasa File, strumienie plikowe, strumienie.
Kurs języka C++ – wykład 3 ( )
Kurs języka C++ – wykład 9 ( )
Treści multimedialne - kodowanie, przetwarzanie, prezentacja Odtwarzanie treści multimedialnych Andrzej Majkowski informatyka +
Systemy operacyjne Wykład 3a Działanie aplikacji okienkowej dr inż. Wojciech Bieniecki Instytut Nauk Ekonomicznych i Informatyki
Zmienne i typy danych w C#
Kurs języka C++ – wykład 4 ( )
Technologie internetowe Wykład 5 Wprowadzenie do skrytpów serwerowych.
Tworzenie graficznego interfejsu użytkownika (GUI)
Programowanie obiektowe Wykład 9 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/15 Dariusz Wardowski.
Wprowadzenie do programowania w WIN32 API Podstawy architektury Windows Witold Bartkiewicz.
Paweł Starzyk Obiektowe metody projektowania systemów
Komunikaty Windows Jacek Matulewski 22 września 2012 Programowanie Windows
STOS. STL (ang. Standard Template Library) jest to biblioteka zawierająca algorytmy, pojemniki, iteratory oraz inne konstrukcje w formie szablonów, gotowe.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
C++ mgr inż. Tomasz Turba Politechnika Opolska 2016.
Programowanie Obiektowe – Wykład 6
Kurs języka C++ – wykład 3 ( )
Klasy, pola, obiekty, metody. Modyfikatory dostępu, hermetyzacja
Akademia C# - Lab2 Zmienne, instrukcje warunkowe, pętle, debugger,
Programowanie Obiektowe – Wykład 2
Programowanie obiektowe – zastosowanie języka Java SE
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
Tworzenie graficznego interfejsu użytkownika (GUI)
Zapis prezentacji:

Jacek Matulewski 21 listopada 2016 Programowanie Windows WinAPI i platforma .NET Jacek Matulewski 21 listopada 2016 http://www.fizyka.umk.pl/~jacek/dydaktyka/winprog/

Mechanizm Platform Invoke w platformie .NET Programowanie Windows Mechanizm Platform Invoke w platformie .NET

Trivia Platformy .NET, WinRT (W8), UWP (W10) tworzą osobną warstwę z własną „wirtualną maszyną” Platforma .NET ułatwia odwołania do niezarządzanych DLL via mechanizm PInvoke Ważne źródło: http://www.pinvoke.net/index.aspx (deklaracja, przykłady użycia, zamienniki w .NET) Tutorial w MSDN: https://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx

Trivia Czynności wykonywane przy Platform Invoke: lokalizacja biblioteki eksportującej funkcję załadowanie jej do pamięci (przy pierwszym uruchomieniu) pobranie adresu funkcji wrzucanie argumentów na stos i wywołanie funkcji (przekazanie kontroli wątku do kodu niezarządzanego) pobranie i konwersja typu zwracanej wartości powrót kontroli do kodu zarządzanego

Trivia https://msdn.microsoft.com/en-us/library/aa719485(v=vs.71).aspx

Atrybut DllImport Atrybut DllImportAttribute pozwala na zadeklarowanie metody statycznej, która reprezentuje funkcję z biblioteki DLL Konstruktor przyjmuje nazwę niezarządzanej biblioteki DLL: public DllImportAttribute(string dllName) Wymaga zadeklarowania przestrzeni nazw: using System.Runtime.InteropServices; Składnia (w najprostszej formie): [DllImport("Biblioteka.dll")] static extern Funkcja(argumenty); Problem konwersji typów

Atrybut DllImport Oryginalna sygnatura funkcji WinAPI: BOOL WINAPI MessageBeep( _In_ UINT uType //sound type ); Import (może być w klasie statycznej, ale niekoniecznie): [DllImport("User32.dll")] static extern bool MessageBeep(uint uType); Odpowiednik w platformie .NET: System.Media.SystemSounds.Beep.Play

Atrybut DllImport Przykład użycia: object sender, EventArgs e) { private void button1_Click( object sender, EventArgs e) { MessageBeep(0); MessageBeep(48); }

Atrybut DllImport Oryginalna sygnatura funkcji WinAPI: int WINAPI MessageBox( _In_opt_ HWND    hWnd, _In_opt_ LPCTSTR lpText, _In_opt_ LPCTSTR lpCaption, _In_     UINT    uType ); Przykładowe wartości uType: MB_OK (0), MB_YESNO (4), MB_ABORTRETRYIGNORE (2), MB_HELP (16384), MB_CANCELTRYCONTINUE (6), MB_ICONERROR (16), MB_ICONQUESTION (32), ...

Atrybut DllImport Import: Zmiana nazwy funkcji – własność EntryPoint [DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = CharSet.Unicode)] static extern int _MessageBox(IntPtr hWnd, String text, String caption, uint type); Zmiana nazwy funkcji – własność EntryPoint Zestaw znaków w argumentach-łańcuchach – CharSet (w WinAPI – tablica znaków, wersja A i W) Odpowiednik w platformie .NET: System.Windows.Forms.MessageBox.Show

Atrybut DllImport Przykład użycia: Odpowiednik w platformie .NET: private void button1_Click(object sender, EventArgs e) { _MessageBox(this.Handle, "Polskie litery: ąćęłńóśżź", "Tytuł", 64); } Odpowiednik w platformie .NET: MessageBox.Show( "Polskie litery: ąćęłńóśżź", "Tytuł", MessageBoxButtons.OK, MessageBoxIcon.Information);

Użycie typów wyliczeniowych Oryginalna sygnatura funkcji WinAPI: UINT WINAPI WinExec( _In_ LPCSTR lpCmdLine, _In_ UINT   uCmdShow ); Wybrane wartości uCmdShow: SW_HIDE (0), SW_MAXIMIZE (3), SW_MINIMIZE (6), SW_RESTORE (9), SW_SHOW (5), SW_DEFAULT (10) Te same wartości w ShowWindow, CreateProcess itd.

Typy wyliczeniowe Import: [DllImport("kernel32.dll")] static extern uint WinExec(string polecenie, uint stanOkna); To nie jest zgodne z duchem platformy .NET – typ wyliczeniowy Te sam problem w MessageBeep i MessageBox Odpowiednik w platformie .NET: System.Diagnostics.Process.Start

Typy wyliczeniowe Typ wyliczeniowy z określonym typem uint - konwersja: public enum StanOkna : uint { Ukryte = 0, Normalme, Zminimalizowane, Zmaksymalizowane, Nieaktywne, Domyślne = 10 }; Import: [DllImport("kernel32.dll")] static extern uint WinExec(string polecenie, StanOkna stanOkna);

Atrybut DllImport Przykład użycia: EventArgs e) { private void button1_Click(object sender, EventArgs e) { uint wynik = WinExec(textBox1.Text, StanOkna.Normalme); if (wynik <= 31) MessageBox.Show("Błąd " + wynik + "! Nie udało się uruchomić " + textBox1.Text); }

Atrybut DllImport Przykład użycia z listą wyboru (ComboBox): private void button1_Click(object sender, EventArgs e) { uint wynik = WinExec(textBox1.Text, (StanOkna)cbStanOkna.SelectedIndex); if (wynik <= 31) MessageBox.Show("Błąd " + wynik + "! Nie udało się uruchomić " + textBox1.Text); }

Demo Funkcje MessageBeep, MessageBox, WinExec Import, wskazanie nazwy funkcji, typ wyliczeniowy

Zwracanie wartości przez referencje Oryginalna sygnatura funkcji WinAPI: BOOL GetDiskFreeSpaceEx( LPCTSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes ); Typy użyte w sygnaturze (zob. MSDN Windows Data Types): LPCTSTR = LPCWSTR (Unicode) lub LPCSTR (ASCII) typedef __nullterminated CONST CHAR *LPCSTR; PULARGE_INTEGER = wskaźnik do LARGE_INTEGER

Zwracanie wartości przez referencje Liczba całkowita 64-bitowa: typedef union _LARGE_INTEGER { struct { DWORD LowPart; LONG  HighPart; }; struct { DWORD LowPart; LONG  HighPart; } u; LONGLONG QuadPart; } LARGE_INTEGER, *PLARGE_INTEGER; Liczba całkowita 64-bitowa: W przypadku, gdy kompilator obsługuje liczby 64-bitowe, należy używać typu LONGLONG. Jeżeli nie – dwóch DWORD.

Zwracanie wartości przez referencje Import: [DllImport("kernel32.dll")] static extern bool GetDiskFreeSpaceEx( string katalog, ref long wolneMiejsceDlaUzytkownika, ref long rozmiarDysku, ref long wolneMiejsceNaDysku); Odpowiednik w platformie .NET: System.IO.DriveInfo

Zwracanie wartości przez referencje Przykład użycia: private int wolneMiejsceNaDysku( string katalogGlownyDysku) { int wolneMiejsceNaDyskuProcenty; long wolneMiejsceDlaUzytkownika = 0; long rozmiarDysku = 0; long wolneMiejsceNaDysku = 0; if (GetDiskFreeSpaceEx( katalogGlownyDysku, ref wolneMiejsceDlaUzytkownika, ref rozmiarDysku, ref wolneMiejsceNaDysku)) { ...

Zwracanie wartości przez referencje Przykład użycia: private int wolneMiejsceNaDysku( string katalogGlownyDysku) { ... if (GetDiskFreeSpaceEx( ... ) { wolneMiejsceNaDyskuProcenty = (int)(100 * (rozmiarDysku – wolneMiejsceNaDysku) / (double)rozmiarDysku); } else wolneMiejsceNaDyskuProcenty = -1; return wolneMiejsceNaDyskuProcenty; }

Zwracanie wartości przez referencje Przykład użycia: public Form1() { InitializeComponent(); string katalogGłównyDysku = System.Environment.GetLogicalDrives()[0]; int procentZajetosci = wolneMiejsceNaDysku(katalogGlownyDysku); if (procentZajetosci >= 0) progressBar1.Value = procentZajetosci; }

Demo Funkcja GetDiskFreeSpaceEx Zwracanie wartości przez referencje

Tablica znaków – łańuchy Oryginalna sygnatura funkcji WinAPI: UINT WINAPI GetWindowsDirectory( _Out_ LPTSTR lpBuffer, // _In_  UINT   uSize ); ASCII: typedef CHAR *LPSTR; UNICODE: typedef WCHAR *LPWSTR; Import: [DllImport("kernel32.dll")] static extern uint GetWindowsDirectory( StringBuilder bufor, uint rozmiarBufora); Odpowiednik w platformie .NET: System.Environment.SystemDirectory

Tablica znaków – łańuchy Przykład użycia (StringBuilder wymaga trochę wysiłku): private void button4_Click(object sender, EventArgs e) { const int MAX_PATH = 260; StringBuilder katalogWindows = new StringBuilder(MAX_PATH); uint rozmiar = (uint)katalogWindows.Capacity; GetWindowsDirectory(katalogWindows, rozmiar); MessageBox.Show(katalogWindows.ToString()); } Tak samo funkcje: GetWindowsDirectory i GetSystemDirectory

Color Picker Cel: chcemy pobierać kolor piksela na ekranie znajdujący się pod kursorem myszy Wyłączamy skalowanie aplikacji – skalowanie pozycji myszy: BOOL WINAPI SetProcessDPIAware(void); Pobieramy pozycję myszy: BOOL WINAPI GetPhysicalCursorPos( _Out_ LPPOINT lpPoint ); Pobieramy obraz (bitmapę) ze wskazanego prostokąta (np. 1×1): BOOL BitBlt(_In_ HDC hdcDest, _In_ int nXDest, _In_ int nYDest, _In_ int nWidth, _In_ int nHeight, _In_ HDC hdcSrc, _In_ int nXSrc, _In_ int nYSrc, _In_ DWORD dwRop); Odpowiednik w platformie .NET: System.Windows.Forms.Cursor.Position Odpowiednik w platformie .NET: System.Drawing.Graphics.CopyFromScreen

Color Picker Import: public static extern bool SetProcessDPIAware(); [DllImport("user32.dll")] public static extern bool SetProcessDPIAware(); public static extern bool GetCursorPos(ref Point lpPoint); public static extern bool GetPhysicalCursorPos(ref Point lpPoint); [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);

Color Picker Przykład użycia (z projektu Huberta Wojtowicza): private static Bitmap pikselEkranu = new Bitmap( 1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb); public static Color PobierzKolorPiksela(Point położenie) { //grafika źródła (ekran) using (Graphics gd = Graphics.FromImage(pikselEkranu)) //grafika bitmapy, w której zostanie zapisany kolor using (Graphics gs = Graphics.FromHwnd(IntPtr.Zero)) { ... } return screenPixel.GetPixel(0, 0); //zwracany jedyny piksel

Color Picker Przykład użycia (z projektu Huberta Wojtowicza): private static Bitmap pikselEkranu = new Bitmap( 1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb); public static Color PobierzKolorPiksela(Point położenie) { ... IntPtr hsDC = gs.GetHdc(); //uchwyt do DC źródła IntPtr hdDC = gd.GetHdc(); //uchwyt do DC celu BitBlt( hdDC, 0, 0, 1, 1, //cel (uchwyt i geometria) hsDC, położenie.X, położenie.Y, //źródło (uchwyt i poł.) (int)CopyPixelOperation.SourceCopy); //tryb wklejania gd.ReleaseHdc(); gs.ReleaseHdc(); //zwalnianie uchwytów }

Color Picker Przykład użycia (wymaga kontrolek Timer, Label, Panel): private void timer1_Tick(object sender, EventArgs e) { Point pozycjaKursora = Cursor.Position; GetPhysicalCursorPos(ref pozycjaKursora); label3.Text = pozycjaKursora.ToString(); panel1.BackColor = PobierzKolorPiksela(pozycjaKursora); }

Zrzut całego ekranu Przykład użycia (zmodyfikowana funkcja pobierająca piksel): public static Bitmap PobierzZrzutEkranu() { RECT obszar = new RECT(); GetWindowRect(GetDesktopWindow(), out obszar); Bitmap bitmap = new Bitmap(obszar.Right - obszar.Left, obszar.Bottom - obszar.Top); using (Graphics gd = Graphics.FromImage(bitmap)) using (Graphics gs = Graphics.FromHwnd(IntPtr.Zero)) ... } return bitmap;

Zrzut całego ekranu Przykład użycia (zmodyfikowana funkcja pobierająca piksel): public static Bitmap PobierzZrzutEkranu() { ... IntPtr hsDC = gs.GetHdc(); IntPtr hdDC = gd.GetHdc(); BitBlt( hdDC, 0, 0, obszar.Right - obszar.Left, obszar.Bottom - obszar.Top, hsDC, 0, 0, (int)CopyPixelOperation.SourceCopy); gd.ReleaseHdc(); gs.ReleaseHdc(); }

Zrzut całego ekranu Deklarowanie struktur danych na potrzeby PInvoke: [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; }

Zrzut ekranu w obrębie okna Zamiast funkcji BitBlt można użyć PrintWindow (służy do kopiowania zawartości okna do wskazanego DC) Nie pozwala na operacje bitowe przy kopiowaniu Oryginalna sygnatura funkcji WinAPI: BOOL PrintWindow(HWND hwnd, HDC  hdcBlt, UINT nFlags); Import: [DllImport("user32.dll")] static extern bool PrintWindow( IntPtr hWnd, IntPtr hDC, int flags);

Zrzut ekranu w obrębie okna Przykład użycia: public static Bitmap PobierzZrzutOkna(IntPtr uchwytOkna, bool tylkoObszarKlienta = false) { RECT obszar = new RECT(); GetWindowRect(uchwytOkna, out obszar); Bitmap bitmap = new Bitmap(obszar.Right - obszar.Left, obszar.Bottom - obszar.Top); using (Graphics gd = Graphics.FromImage(bitmap)) PrintWindow(uchwytOkna, gd.GetHdc(), tylkoObszarKlienta?1:0); } return bitmap;

Demo Funkcja BitBlt, PrintWindow Pobieranie zrzutów ekanu, color picker

Demo Funkcja EnumWindows, EnumChildWindows Zadanie domowe: na zrzucie ekranu zaznaczyć położenia wszystkich okien (w tym kontrolek) z tytułem i uchwytem

Atrybut DllImport Niektóre pola i własności atrybutu DllImportAttribute: CallingConvention (Cdecl, StdCall, ThisCall, Winapi) CharSet (zestaw znaków: Ansi, Unicode) EntryPoint (nazwa importowanej funkcji) SetLastError (wywoływana jest metoda SetLastError, jej wynik można pobrać funkcją GetLastError) MarshalAsAttribute – określa niezarządzany typ argumentu lub wartości zwracanej przez funkcję; zwykle zbędny; jedyny wyjątek to niejednoznaczność łańcuchów [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool MessageBeep(uint uType); Atrybuty In i Out określają kierunek konwersji argumentów

Atrybut MarshalAs Przykład dla argumentów (zał. Unicode): [DllImport("User32.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.I4)] static extern Int32 MessageBoxEx( IntPtr hWnd, //unicode [param: MarshalAs(UnmanagedType.LPTStr)] String lpText, [param: MarshalAs(UnmanagedType.LPTStr)] String lpCaption, //32-bitowa (4-bajtowa) liczba całkowita bez znaku [param: MarshalAs(UnmanagedType.U4)] UInt32 uType, //16-bitowa (2-bajtowa) liczba całkowita bez znaku [param: MarshalAs(UnmanagedType.U2)] UInt16 wLanguageId); https://www.codeproject.com/articles/66245/marshaling-with-csharp-chapter-1-introducing-marsh.aspx

Programowanie Windows Komunikaty Windows

Identyfikacja adresata komunikatu Funkcja FindWindow (już poznaliśmy) zwraca uchwyt okna o podanej klasie lub tytule HWND WINAPI FindWindow( _In_opt_ LPCTSTR lpClassName, _In_opt_ LPCTSTR lpWindowName ); Import: [DllImport("user32.dll")] static extern HWND FindWindow(string nazwaKlasy, string nazwaOkna);

Wysyłanie komunikatu Funkcje SendMessage i PostMessage (także już znane) wysyłają komunikaty do okna o podanym uchwycie LRESULT WINAPI SendMessage( _In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam); Import: [DllImport("user32.dll")] static extern int SendMessage( HWND hwnd, uint Msg, int wParam, int lParam);

Wysyłanie komunikatu Stałe: Lista komunikatów: public const int WM_CLOSE = 0x0010; public const int WM_SYSCOMMAND = 0x0112; public const int WM_NCMOUSEMOVE = 0x00A0; public const int WM_PAINT = 0x000F; public const int WM_KEYDOWN = 0x0100; public const int WM_KEYUP = 0x0101; public const int WM_CHAR = 0x0102; Lista komunikatów: http://www.pinvoke.net/default.aspx/Enums/WindowsMessages.html

Wysyłanie komunikatu Przykład użycia: { private void button1_Click(object sender, EventArgs e) { string nazwaOkna = textBox1.Text; HWND uchwyt = FindWindow(null, nazwaOkna); if (uchwyt != HWND.Zero) SendMessage(uchwyt, WM_CLOSE, 0, 0); else MessageBox.Show("Nie ma okna o tytule \"" + nazwaOkna + "\""); }

Odbieranie komunikatu Nadpisywanie procedury okna (ListBox, MultiColumn = true, ColumnWidth = 30): protected override void WndProc(ref Message m) { if (m.Msg!=308) listBox1.Items.Add(m.Msg); //308 = WM_CTLCOLORLISTBOX base.WndProc(ref m); }

Odbieranie komunikatu Nadpisywanie procedury okna (ListBox, MultiColumn = true, ColumnWidth = 30): switch(m.Msg) { case WM_NCMOUSEMOVE: long lParam=(long)m.LParam; long x=lParam & 0x0000FFFF; long y=(lParam & 0xFFFF0000) >> 16; label1.Text = "(Komunikat) Mysz poza obszarem klienta: " + x + "," + y; break; }