亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? animation.html

?? This tutorial attempts to get you started developing with the Win32 API as quickly and clearly as po
?? HTML
字號:
<HTML><LINK HREF="style.css" REL="STYLESHEET" TYPE="text/css"><HEAD><TITLE>Timers and Animation</TITLE></HEAD><BODY><FONT SIZE="-1">[ <A HREF="./index.html">contents</A>| <A HREF="http://www.winprog.org/">#winprog</A>]</FONT><HR><H1>Timers and Animation</H1><P>Example: anim_one</P><IMG SRC="images/anim_one.gif" ALT="[images/anim_one.gif]" ALIGN="right"><H2>Setting up</H2>Before we get things animated, we need to set up a structure to store the position ofthe ball between updates.  This struct will store the current position and size of the ball,as well as the delta values, how much we want it to move each frame.<P>Once we have the structure type declared, we also declare a global instance of the struct.  Thisis ok since we only have one ball, if were were going to animate a bunch of them, you'd probably wantto use an array or other container (such as a linked list in C++) to store them in a more convenientway.<PRE CLASS="SNIP">const int BALL_MOVE_DELTA = 2;typedef struct _BALLINFO {    int width;    int height;    int x;    int y;    int dx;    int dy;}BALLINFO;BALLINFO g_ballInfo;</PRE>We've also defined a constant <CODE>BALL_MOVE_DELTA</CODE> which is how far we want the ball to move oneach update.  The reason we store deltas in the <CODE>BALLINFO</CODE> structure as well is that we wantto be able to move the ball left or right and up and down independantly, <CODE>BALL_MOVE_DELTA</CODE>is just a handy name to give the value so we can change it later if we want.<P>Now we need to initialize this structure after we load our bitmaps:<PRE CLASS="SNIP">    BITMAP bm;</PRE><PRE CLASS="SNIP">    GetObject(g_hbmBall, sizeof(bm), &bm);    ZeroMemory(&g_ballInfo, sizeof(g_ballInfo));    g_ballInfo.width = bm.bmWidth;    g_ballInfo.height = bm.bmHeight;    g_ballInfo.dx = BALL_MOVE_DELTA;    g_ballInfo.dy = BALL_MOVE_DELTA;</PRE><P>The ball starts off in the top left corner, moving to the right and down according to the <CODE>dx</CODE> and <CODE>dy</CODE> members of <CODE>BALLINFO</CODE>.<H2>Setting the Timer</H2>The easiest way to add a simple timer into a window program is with <CODE>SetTimer()</CODE>, it's not the best, and it'snot recommended for real multimedia or full games, however it's good enough for simple animations like this.  When you need something better take a look at <CODE>timeSetEvent()</CODE> in MSDN; it's more accurate.<PRE CLASS="SNIP">const int ID_TIMER = 1;</PRE><PRE CLASS="SNIP">    ret = SetTimer(hwnd, ID_TIMER, 50, NULL);    if(ret == 0)        MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);</PRE>Here we've declared a timer id so that we can refer to it later (to kill it) and then set the timerin the <CODE>WM_CREATE</CODE> handler of our main window.  Each time the timer elapses, it will senda <CODE>WM_TIMER</CODE> message to the window, and pass us back the ID in <CODE>wParam</CODE>.  Since we only have one timer we don't need the ID, but it's useful if you set more than one timerand need to tell them apart.<P>We've set the timer to elapse every 50 milliseconds, which results in approximately 20 frames per second.  Approximatelybecause like I said, <CODE>SetTimer()</CODE> is a little inaccurate, but this isn't critical code, and a few millisecondshere or there won't kill us.<H2>Animating in WM_TIMER</H2>Now when we get <CODE>WM_TIMER</CODE> we want to calculate the new position for the ball and draw it's updatedposition.<PRE CLASS="SNIP">    case WM_TIMER:    {        RECT rcClient;        HDC hdc = GetDC(hwnd);        GetClientRect(hwnd, &rcClient);        UpdateBall(&rcClient);        DrawBall(hdc, &rcClient);        ReleaseDC(hwnd, hdc);    }    break;</PRE><P>I've put the code for updating and drawing the ball in their own functions.  This is good practice, andit lets us draw the ball from either <CODE>WM_TIMER</CODE> or <CODE>WM_PAINT</CODE> without duplicating code, note that the methodwe use to get the <CODE>HDC</CODE> in each case is different, so it's best to leave this code in the message handlersand pass the result into the <CODE>DrawBall()</CODE> function.<PRE CLASS="SNIP">void UpdateBall(RECT* prc){    g_ballInfo.x += g_ballInfo.dx;    g_ballInfo.y += g_ballInfo.dy;    if(g_ballInfo.x < 0)    {        g_ballInfo.x = 0;        g_ballInfo.dx = BALL_MOVE_DELTA;    }    else if(g_ballInfo.x + g_ballInfo.width > prc->right)    {        g_ballInfo.x = prc->right - g_ballInfo.width;        g_ballInfo.dx = -BALL_MOVE_DELTA;    }    if(g_ballInfo.y < 0)    {        g_ballInfo.y = 0;        g_ballInfo.dy = BALL_MOVE_DELTA;    }    else if(g_ballInfo.y + g_ballInfo.height > prc->bottom)    {        g_ballInfo.y = prc->bottom - g_ballInfo.height;        g_ballInfo.dy = -BALL_MOVE_DELTA;    }}</PRE>All this does is some basic math, we add the delta value to the x position to move the ball.  If the ball goesoutside the client area, move it back in range and change the delta value to the opposite direction so that theball "bounces" off the sides.<PRE CLASS="SNIP">void DrawBall(HDC hdc, RECT* prc){    HDC hdcBuffer = CreateCompatibleDC(hdc);    HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);    HBITMAP hbmOldBuffer = SelectObject(hdcBuffer, hbmBuffer);    HDC hdcMem = CreateCompatibleDC(hdc);    HBITMAP hbmOld = SelectObject(hdcMem, g_hbmMask);    FillRect(hdcBuffer, prc, GetStockObject(WHITE_BRUSH));    BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCAND);    SelectObject(hdcMem, g_hbmBall);    BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCPAINT);    BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);    SelectObject(hdcMem, hbmOld);    DeleteDC(hdcMem);    SelectObject(hdcBuffer, hbmOldBuffer);    DeleteDC(hdcBuffer);    DeleteObject(hbmBuffer);}</PRE>This is essentially the same drawing code as the past few examples, with the exception that it gets the position and dimentions of the ball from the <CODE>BALLINFO</CODE> structure.  There is however one important difference...<H2>Double Buffering</H2>When doing your drawing directly to the <CODE>HDC</CODE> of the window, it's entirely possible that the screenwill get updated before you're done... for example after you draw the mask and before you draw the colour imageover top, the user might see a flicker of the back background before your program has a chance to draw over itin colour.  The slower your computer and the more drawing operations that you do, the more flicker will be apparentand eventually it will look like a big jumbled mess.<P>This is terribly distracting, and we can solve it simply by doing all the drawing in memory first, and thencopying the completed masterpiece to the screen in a single <CODE>BitBlt()</CODE> so that the screen is updateddirectly from the old image, to the complete new image with none of the individual operations visible.<P>To do this, we create a temporary <CODE>HBITMAP</CODE> in memory that is the exact size of the area we are going to draw to on the screen.  We also need an <CODE>HDC</CODE> so that we can <CODE>BitBlt()</CODE> to the bitmap.<PRE CLASS="SNIP">    HDC hdcBuffer = CreateCompatibleDC(hdc);    HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);    HBITMAP hbmOldBuffer = SelectObject(hdcBuffer, hbmBuffer);</PRE>Now that we have a place to draw to in memory, all of the drawing operations use <CODE>hdcBuffer</CODE> instead of <CODE>hdc</CODE> (the window) and the results are stored on the bitmap in memory untill we are complete.  We can nowcopy the whole thing over to the window in one shot.<PRE CLASS="SNIP">    BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);</PRE>That's it, and we clean up our <CODE>HDC</CODE>s and <CODE>HBITMAP</CODE>s as usual.<H3>Faster Double Buffering</H3>In this example I am creating and destroying the bitmap used for double buffering each frame, I did this basicallybecause I wanted to be able to size the window so it's easier to just always create a new buffer than to trackwhen the window position changes and resize the buffer.  It would be more efficient to create a global double buffer bitmap and either not allow the window to resize or only resize the bitmap when the window resized, insteadof creating it and destroying it all the time.  It's up to you to implement this if you want to optimize the drawingfor a game or something.<H2>Killing the Timer</H2>When our window is destroyed, it's a good idea to release all resources we used, and in this case thatincludes the timer we set.  To stop it, we simply call <CODE>KillTimer()</CODE> and pass in the ID that we used whenwe created it.<PRE CLASS="SNIP">    KillTimer(hwnd, ID_TIMER);</PRE><HR><FONT SIZE="-1">Copyright &copy; 1998-2003, Brook Miles (<A HREF="mailto:forger(nospam)winprog.org">theForger</A>).  All rights reserved.</FONT><SCRIPT language="JavaScript"><!--   var re = /\(nospam\)/ig;   var str;   for(i = 0;i < document.links.length;i++)    {      str = "" + document.links(i).href;      if(str.search(re) != -1)         document.links(i).href = str.replace(re, "@");      str = "" + document.links(i).innerHTML;      if(str.search(re) != -1)         document.links(i).innerHTML = str.replace(re, "@");   }--></SCRIPT></BODY></HTML>

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲国产精品精华液网站| 中文字幕日韩av资源站| 91久久精品网| a4yy欧美一区二区三区| 丁香桃色午夜亚洲一区二区三区| 久久 天天综合| 久久99久久99| 国产成人在线影院 | 91视频在线看| 色综合视频一区二区三区高清| 99精品国产视频| 色哟哟日韩精品| 欧美日韩一卡二卡三卡| 欧美一区二区三区系列电影| 日韩一区二区三区在线观看| 欧美成人aa大片| 欧美国产精品一区| 亚洲美女精品一区| 日日夜夜精品免费视频| 国产综合久久久久久久久久久久| 色视频成人在线观看免| 色狠狠色狠狠综合| 91精品国产欧美一区二区18| 精品福利视频一区二区三区| 中文字幕免费观看一区| 一区二区三区成人在线视频| 日韩电影免费在线| 成人影视亚洲图片在线| 在线看日本不卡| 精品少妇一区二区| 亚洲免费电影在线| 美女一区二区视频| jvid福利写真一区二区三区| 欧美日韩国产高清一区二区三区 | 一本大道av伊人久久综合| 欧美在线看片a免费观看| 日韩免费电影一区| 亚洲日本丝袜连裤袜办公室| 青青青伊人色综合久久| 91论坛在线播放| 日韩欧美中文一区二区| 亚洲欧美一区二区久久| 精品一区二区三区久久| 在线视频你懂得一区| 久久精品男人天堂av| 亚洲国产aⅴ天堂久久| 国产成人精品网址| 91精品国产色综合久久ai换脸| 国产精品丝袜在线| 国产高清精品久久久久| 欧美日韩一区不卡| 亚洲欧美激情小说另类| 国产精品资源在线观看| 欧美二区在线观看| 亚洲女与黑人做爰| 成人晚上爱看视频| 精品久久久网站| 日韩在线观看一区二区| 色综合久久久久久久久久久| 国产午夜亚洲精品理论片色戒| 肉肉av福利一精品导航| 在线观看亚洲精品视频| 国产精品久久三区| 国产成人精品三级麻豆| 久久奇米777| 精品在线视频一区| 日韩欧美久久一区| 青青草一区二区三区| 欧美视频一区在线观看| 亚洲影院在线观看| 欧美亚洲高清一区二区三区不卡| 国产精品成人免费精品自在线观看| 国产电影精品久久禁18| 久久免费美女视频| 国产剧情在线观看一区二区| 久久影视一区二区| 国产一区二三区好的| 久久久亚洲精品一区二区三区| 久久国产精品72免费观看| 精品毛片乱码1区2区3区| 免费高清在线视频一区·| 欧美一区二区免费| 久久精品国产亚洲a| 久久色.com| 不卡免费追剧大全电视剧网站| 欧美高清在线一区二区| 欧美剧情电影在线观看完整版免费励志电影 | 狠狠色狠狠色综合系列| 久久综合九色综合欧美就去吻| 国产一区二区福利视频| 中文字幕第一区二区| 99re亚洲国产精品| 亚洲在线观看免费视频| 欧美高清视频不卡网| 美美哒免费高清在线观看视频一区二区 | 欧美日韩美女一区二区| 日精品一区二区| 欧美mv日韩mv国产网站app| 国产不卡视频在线观看| 亚洲品质自拍视频| 欧美裸体bbwbbwbbw| 精品无人区卡一卡二卡三乱码免费卡 | 一区二区三区日韩| 日韩午夜在线影院| 成人黄色综合网站| 亚洲h在线观看| 精品国产91亚洲一区二区三区婷婷| 成人综合日日夜夜| 日韩和欧美的一区| 中文字幕乱码日本亚洲一区二区| 在线免费观看日本欧美| 黄网站免费久久| 亚洲免费大片在线观看| 337p日本欧洲亚洲大胆色噜噜| 91免费观看视频| 国产一区二区不卡在线| 亚洲美女屁股眼交3| 久久久亚洲精品石原莉奈| 欧美色电影在线| 风间由美性色一区二区三区| 五月天一区二区三区| 国产精品污www在线观看| 91精品国产一区二区三区蜜臀 | 天堂久久久久va久久久久| 欧美国产视频在线| 日韩欧美一二三区| 色婷婷精品久久二区二区蜜臂av| 国产一区二区三区日韩| 亚洲成av人片在线观看无码| 国产女主播在线一区二区| 717成人午夜免费福利电影| 91网站在线观看视频| 国产传媒欧美日韩成人| 蜜臀va亚洲va欧美va天堂 | 免费观看久久久4p| 一区二区三区免费在线观看| 国产精品美女一区二区在线观看| 欧美一级精品在线| 91精品国产91热久久久做人人 | 欧美日本乱大交xxxxx| 91色.com| av电影天堂一区二区在线观看| 国产在线不卡一区| 久久成人免费网| 日韩精品1区2区3区| 亚洲国产视频在线| 亚洲欧美乱综合| 亚洲精品高清在线| 亚洲视频一区在线| 国产精品久久久久久久浪潮网站| 欧美高清在线精品一区| 国产人久久人人人人爽| 国产日韩精品视频一区| 久久久久九九视频| 国产日本欧洲亚洲| 亚洲欧洲精品天堂一级 | 91精品福利在线| 日本乱人伦aⅴ精品| 欧洲视频一区二区| 欧美日韩精品一区二区三区蜜桃 | 色婷婷亚洲精品| 欧美色网站导航| 欧美老年两性高潮| 91精品一区二区三区在线观看| 欧美顶级少妇做爰| 日韩精品一区二区三区视频| 精品国产乱码久久久久久夜甘婷婷| 精品国产免费一区二区三区四区| 26uuu亚洲| 中文字幕永久在线不卡| 亚洲一区二区三区在线看| 日韩在线一二三区| 国产在线观看免费一区| 99国内精品久久| 欧美日韩国产大片| 26uuu久久综合| 日韩一区在线看| 婷婷开心激情综合| 国产精品一区二区免费不卡| 99在线热播精品免费| 欧美高清www午色夜在线视频| 26uuu色噜噜精品一区| 亚洲男人的天堂网| 久久激情五月婷婷| yourporn久久国产精品| 在线电影一区二区三区| 国产欧美视频一区二区| 亚洲国产cao| 国产福利一区二区三区| 欧美午夜精品久久久久久孕妇| 日韩精品一区在线观看| 中文字幕中文乱码欧美一区二区| 丝袜美腿一区二区三区| 成人精品国产一区二区4080| 欧美精品少妇一区二区三区| 欧美激情综合五月色丁香 | 欧美一级搡bbbb搡bbbb| 国产精品免费视频观看| 看电影不卡的网站| 欧美最猛性xxxxx直播|