<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>pamiętnik programisty &#187; winapi</title>
	<atom:link href="http://piotr.doniec.eu/devlog/tag/winapi/feed/" rel="self" type="application/rss+xml" />
	<link>http://piotr.doniec.eu/devlog</link>
	<description></description>
	<lastBuildDate>Wed, 28 Dec 2011 23:52:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Przezroczyste okienka z WinAPI</title>
		<link>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 12:24:08 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[winapi]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=270</guid>
		<description><![CDATA[Wraz z pojawieniem się systemu Windows 2000, pojawiły się nowe funkcje systemowego API. Jedną z nich jest możliwość tworzenia okien o dowolnym stopniu przezroczystości. Efekt jest dość ciekawy i sporo programów ma możliwość ustawienia przezroczystości własnego okienka. Moim celem było umożliwienie sterowania przezroczystością okien centralnie z jednego programu i to nie zależnie od tego czy [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-339 alignleft" title="transparent_windows2" src="http://piotr.doniec.eu/devlog/wp-content/uploads/2009/10/transparent_windows21.jpg" alt="Przezroczyste okna z winAPI" width="244" height="220" />Wraz z pojawieniem się systemu Windows 2000, pojawiły się nowe funkcje systemowego API. Jedną z nich jest możliwość tworzenia okien o dowolnym stopniu przezroczystości. Efekt jest dość ciekawy i sporo programów ma możliwość ustawienia przezroczystości własnego okienka. Moim celem było umożliwienie sterowania przezroczystością okien centralnie z jednego programu i to nie zależnie od tego czy okno takie zostało do tego przystosowane czy też nie. Po przeczytaniu tego wpisu, każdy samodzielnie będzie mógł napisać podobną aplikację</p>
<p><span id="more-270"></span></p>
<p>Aby istniała możliwość ustawiania przezroczystości dla okna, musi być ono utworzone w sposób do tego przystosowany. Wystarczy skorzystać z innej funkcji tworzącej okno, nie <code>CreateWindow</code>, a <code>CreateWindowEx</code><br />
[cc lang="c"]<br />
HWND CreateWindowEx(<br />
  DWORD dwExStyle,<br />
  LPCTSTR lpClassName,<br />
  LPCTSTR lpWindowName,<br />
  DWORD dwStyle,<br />
  int x,<br />
  int y,<br />
  int nWidth,<br />
  int nHeight,<br />
  HWND hWndParent,<br />
  HMENU hMenu,<br />
  HINSTANCE hInstance,<br />
  LPVOID lpParam<br />
);<br />
[/cc]<br />
To co umożliwia później modyfikacje przezroczystości jest ukryte w ramach dodatkowego stylu okna, podawanego poprzez argument <code>dwExStyle</code>. Lista dopuszczalnych wartości jest długa, ale warto się z nią zapoznać. W tym konkretnym przypadku należy zainteresować się wartością <code>WS_EX_LAYERED</code>, utworzone wtedy okno będzie tzw. Layered Window, które obsługuje modyfikacje przezroczystości. Do ustawienia nowej wartości kanału alpha służy <code>SetLayeredWindowAttributes(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWROD dwFlags)</code> &#8211; szczegóły w dokumentacji.<br />
Pełny kod tworzący przykładowe, półprzezroczyste okno:<br />
[cc lang="c"]<br />
#include <windows.h></p>
<p>LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);</p>
<p>int WINAPI WinMain(HINSTANCE hInstance,	HINSTANCE hPrevInstance,<br />
LPSTR lpCmdLine, int nCmdShow)<br />
{<br />
  MSG msg;<br />
  HWND hwnd;<br />
  WNDCLASSEX wcx;</p>
<p>  wcx.cbSize = sizeof(wcx);<br />
  wcx.style = CS_HREDRAW | CS_VREDRAW;<br />
  wcx.lpfnWndProc = WndProc;<br />
  wcx.cbClsExtra = 0;<br />
  wcx.cbWndExtra = 0;<br />
  wcx.hInstance = hInstance;<br />
  wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);<br />
  wcx.hCursor = LoadCursor(NULL, IDC_ARROW);<br />
  wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);<br />
  wcx.lpszMenuName = (LPCSTR)&#8221;MainMenu&#8221;;<br />
  wcx.lpszClassName = (LPCSTR)&#8221;MainWClass&#8221;;<br />
  wcx.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(5), IMAGE_ICON,<br />
  GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), (UINT)LR_DEFAULTCOLOR);</p>
<p>  RegisterClassEx(&#038;wcx);</p>
<p>  hwnd = CreateWindowEx(WS_EX_LAYERED, (LPCSTR)&#8221;MainWClass&#8221;, (LPCSTR)&#8221;Sample&#8221;, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND)NULL,  (HMENU)NULL, hInstance, (LPVOID) NULL);</p>
<p>  ShowWindow(hwnd, nCmdShow);<br />
  SetLayeredWindowAttributes(hwnd, 0, 180, LWA_ALPHA);<br />
  UpdateWindow(hwnd);</p>
<p>  while(GetMessage(&#038;msg, NULL,  0, 0))<br />
  {<br />
    TranslateMessage(&#038;msg);<br />
    DispatchMessage(&#038;msg);<br />
  }</p>
<p>  return msg.wParam;<br />
}</p>
<p>LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)<br />
{<br />
  switch(uMsg)<br />
  {<br />
    case WM_CREATE:<br />
      return 0;</p>
<p>    case WM_PAINT:<br />
      return 0;</p>
<p>    case WM_DESTROY:<br />
      PostQuitMessage(0);<br />
      return 0;</p>
<p>    default:<br />
      return DefWindowProc(hwnd, uMsg, wParam, lParam);<br />
  }<br />
  return 0;<br />
}<br />
[/cc]</p>
<p>To co należy zrobić, aby kontrolować przezroczystość okien innych niż własne przedstawia się następująco:</p>
<ol>
<li>1. Pobrać wszystkie otwarte okna typu top-level</li>
<li>2. Nadać oknom styl <code>dwExStyle</code></li>
<li>3. Zmienić wartość kanału alpha</li>
</ol>
<p><strong>1. Pobrać wszystkie otwarte okna typu top-level</strong><br />
Dobrym pomysłem wydaje się pobranie uchwytu do rodzica wszystkich okien(Desktop/Pulpit) i przejście w pętli po liście jego dzieci (jak wiadomo każde okno ma kilka przydatnych wskaźników, między innymi do okna-brata). Mogłoby to wyglądać tak:<br />
[cc lang="c"]<br />
HWND hDesktop = GetDesktopWindow();<br />
HWND hChild = GetWindow(hDesktop, GW_CHILD);<br />
HWND hTemp;<br />
/* &#8230; */<br />
while(hTemp != GetWindow(hChild, GW_HWNDLAST))<br />
{<br />
  /* &#8230; */<br />
  hTemp = GetWindow(hChild, GW_HWNDNEXT);<br />
}<br />
[/cc]<br />
Pomysł <strong>zły</strong> ! Okazuje się że taka pętla może działać w nieskończoność. Wzmianaka na temat takiego przypadku znajduje się nawet w dokumentacji. Dlatego należy wykorzystać inny sposób, polegający na użyciu funkcji <code>BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)</code>:<br />
[cc lang="c"]<br />
EnumWindows(EnumWindowsProc, NULL);<br />
/* &#8230; */<br />
BOOL CALLBACK EnumWindowsProc(HWND hwndChild, LPARAM lParam)<br />
{<br />
  char buffer[100];</p>
<p>  int count = GetWindowText(hwndChild, buffer, 100);<br />
  if(count &#038;&#038; IsWindowVisible(hwndChild))<br />
  {<br />
    /* &#8230; */<br />
  }<br />
  return TRUE;<br />
}<br />
[/cc]</p>
<p><strong>2. Nadać oknom styl <code>dwExStyle</code></strong><br />
Wydaje się najtrudniejsze, przecież dodatkowy styl należy podać przy tworzeniu okna, a okna które widzimy zostały już przecież utworzone. Na szczęście z pomocą przychodzi funkcja <code>LONG SetWindowLong(HWND hWnd, int iIndex, LONG dwNewLong)</code>:<br />
[cc lang="c"]<br />
SetWindowLong(hwndChild, GWL_EXSTYLE, WS_EX_LAYERED);<br />
[/cc]</p>
<p><strong>3. Zmienić wartość kanału alpha</strong><br />
Bardziej uważni czytelnicy już na pewno wiedzą jak wygląda zestaw parametrów i jak skorzystać z <code>SetLayeredWindowAttributes</code>. Wykorzystanie pokazane 3 listingi wyżej, przy okazji tworzenia &#8222;własnego&#8221; przezroczystego okna.</p>
<p>I to tyle  tym temacie, wypada jeszcze stworzyć GUI, może obsługę tray&#8217;a. Program wydaje się &#8222;magiczny&#8221; a korzysta raptem z 4 funkcji API systemowego.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tworzenie okienka w asm</title>
		<link>http://piotr.doniec.eu/devlog/2009/09/tworzenie-okienka-w-asm/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/09/tworzenie-okienka-w-asm/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 12:08:45 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[asm]]></category>
		<category><![CDATA[winapi]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=244</guid>
		<description><![CDATA[Wiadomo że stworzenie okienka przy wykorzystaniu języka C i WinAPI nie jest zadaniem trudnym. Nawet w dokumentacji od MS można znaleźć gotowy przykład. Jest to natomiast zadanie bardzo żmudne i z reguły z pełnym zrozumieniem pól i dopuszczalnych wartości dla wymaganych struktur robi się to tylko raz. Potem albo się kopiuje gotowy standardowy kod wprowadzając [...]]]></description>
			<content:encoded><![CDATA[<p>Wiadomo że stworzenie okienka przy wykorzystaniu języka C i WinAPI nie jest zadaniem trudnym. Nawet w dokumentacji od MS można znaleźć gotowy przykład. Jest to natomiast zadanie bardzo żmudne i z reguły z pełnym zrozumieniem pól i dopuszczalnych wartości dla wymaganych struktur robi się to tylko raz. Potem albo się kopiuje gotowy standardowy kod wprowadzając tylko pewne czasami zmiany odbiegającego od typowego zastosowania, albo przyjmuje że &#8222;się umie&#8221; i &#8222;zna fundament&#8221; i przesiada na WindowsForms. Ale można pójść w drugą stronę, stworzyć okienko w assmeblerze i tym samym uzyskać miano rycerza hardcoru.<span id="more-244"></span></p>
<p>Może dziwić ale zbudowanie okna korzystając z języka maszynowego nie jest trudno. Objętość programu jest zbliżona do tego utworzonego standardowo z wykorzystaniem C. Ponadto korzystając z kompilatora dostarczonego przez Microsoft (MASM) istnieje możliwość bardzo łatwego dostępu do funkcji API systemu Windows. Ponad to kompilator dostarcza wiele ułatwiających życie makr.</p>
<p>[cc lang="asm"]<br />
.386<br />
.model flat,stdcall<br />
option casemap:none<br />
include		c:\masm32\include\windows.inc<br />
include 	c:\masm32\include\user32.inc<br />
includelib	c:\masm32\lib\user32.lib<br />
include		c:\masm32\include\kernel32.inc<br />
includelib	c:\masm32\lib\kernel32.lib</p>
<p>WinMain proto <img src='http://piotr.doniec.eu/devlog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> WORD,:DWORD,:DWORD,:DWORD</p>
<p>.data	; zainicjalizowanie zmienne<br />
	ClassName db &#8222;SimpleWinClass&#8221;,0<br />
	AppName db &#8222;Our first Window&#8221;,0<br />
.data?	; niezainicjalizowane zmienne<br />
	hInstance HINSTANCE ?<br />
	CommandLine LPSTR	?<br />
.code<br />
	start:<br />
		invoke GetModuleHandle,NULL<br />
		mov hInstance,eax<br />
		invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT<br />
		invoke ExitProcess,0</p>
<p>WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD<br />
	LOCAL wc:WNDCLASSEX<br />
	LOCAL msg:MSG<br />
	LOCAL hwnd:HWND</p>
<p>	mov wc.cbSize,SIZEOF WNDCLASSEX<br />
	mov wc.style,CS_HREDRAW or CS_VREDRAW<br />
	mov wc.lpfnWndProc,OFFSET WndProc<br />
	mov wc.cbClsExtra,NULL<br />
	mov wc.cbWndExtra,NULL<br />
	push hInstance<br />
	pop wc.hInstance<br />
	mov wc.hbrBackground,COLOR_WINDOW+1<br />
	mov wc.lpszMenuName,NULL<br />
	mov wc.lpszClassName, OFFSET ClassName<br />
	invoke LoadIcon,NULL,IDI_APPLICATION<br />
	mov wc.hIcon,eax<br />
	mov wc.hIconSm,eax<br />
	invoke LoadCursor,NULL,IDC_ARROW<br />
	mov wc.hCursor,eax<br />
	invoke RegisterClassEx,addr wc<br />
	invoke CreateWindowEx,NULL,\<br />
                ADDR ClassName,\<br />
                ADDR AppName,\<br />
                WS_OVERLAPPEDWINDOW,\<br />
                CW_USEDEFAULT,\<br />
                CW_USEDEFAULT,\<br />
                CW_USEDEFAULT,\<br />
                CW_USEDEFAULT,\<br />
                NULL,\<br />
                NULL,\<br />
                hInst,\<br />
                NULL<br />
    mov hwnd,eax<br />
    invoke ShowWindow,hwnd,CmdShow<br />
    invoke UpdateWindow,hwnd    </p>
<p>    .WHILE TRUE<br />
    	invoke GetMessage,ADDR msg,NULL,0,0<br />
    	.BREAK .IF(!eax)<br />
    	invoke TranslateMessage,ADDR msg<br />
    	invoke DispatchMessage,ADDR msg<br />
    .ENDW</p>
<p>    mov eax,msg.wParam<br />
	ret</p>
<p>WinMain endp</p>
<p>WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM</p>
<p>	.IF uMsg==WM_DESTROY<br />
		invoke PostQuitMessage,NULL<br />
	.ELSE<br />
		invoke DefWindowProc,hWnd,uMsg,wParam,lParam<br />
		ret<br />
	.ENDIF<br />
	xor eax,eax<br />
	ret</p>
<p>WndProc endp</p>
<p>	end start</p>
<p>[/cc]</p>
<p>Nie ma co wiele tłumaczyć. Kod jaki jest interpretowany przez MASM wygląda już niemalże jak język wysokiego poziomu(niektórzy mówią że C to język niskiego poziomu, ale to dlatego że nie umieli znaleźć określenia dla Javy, C# itp.) Bardzo fajnym makrem jest <code>invoke</code> uruchamiające zadaną procedurę i umożliwiające podanie listy argumentów poprzez rozdzielenie przecinkiem. Bardzo przyjemna alternatywa dla push&#8217;owania w odwrotnej kolejności.<br />
Jedyny wniosek jaki można wysnuć to to że jeżeli ktoś umie programować z wykorzystaniem WinAPI w C, to i bez problemu zastosuje go w assemblerze. Oczywiście nie ma obowiązku korzystania z MASM, do API można się także dostać korzystać z innych assemblerów np. NASM ( polacam zapoznanie się z nasmx).</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/09/tworzenie-okienka-w-asm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

