/* dbvabout.c - DibVwr About Dialog with an added surprise * * Written by Alfons Hoogervorst, 1995-1997, proteus@worldaccess.nl. */ /* This module directly accesses the HDIBVWR data managed by the * DibWindow. At the time of writing the dibwin.c interface functions * we're not completed entirely. See the do_scroll window for * examples of directly accessing the HDIBVWR data of a DIB window. */ /* * @DOC * @module dbvabout.c | * This module is only interesting because it directly accesses the * data stored in the DibWindow. This data is manipulated to perform * the scrolling effect in the about dialog. * @index dvabout.c | func */ #include "compiler.h" #include #include "dbvabout.h" #include "dibwin.h" #include "dibfunc.h" #include "windbg.h" #include "winfuncs.h" #define ID_TIMER (667) #define TIME_OUT (75) /*** Under Win32 HMODULE == HINSTANCE ***/ #define get_current_hinstance() \ ((HINSTANCE)GetModuleHandle(NULL)) #define IsScrolling(hDlg) \ GetWindowLong((hDlg), DWL_USER) #define SetScrolling(hDlg) \ SetWindowLong((hDlg), DWL_USER, 1) #define PROP_SCROLL_HWND "prop_Scroll_Hwnd" #define SetScrollWindow(hDlg, hWnd) \ SetProp(hDlg, PROP_SCROLL_HWND, (HANDLE)(hWnd)) #define GetScrollWindow(hDlg) (HWND)GetProp(hDlg, PROP_SCROLL_HWND) #ifdef __cplusplus extern "C" { #endif BOOL CALLBACK dbv_about_dlgproc(HWND, UINT, WPARAM, LPARAM); static BOOL dbv_about_oninitdialog (HWND); static BOOL dbv_about_onshowwindow (HWND, BOOL); static BOOL dbv_about_ontimer (HWND); static BOOL dbv_about_oncommand (HWND, UINT, UINT, HWND); static VOID do_scroll (HWND, HDIBVWR); #ifdef __cplusplus } #endif /*****************/ static int _nMovX; static int _nMovY; static int _nWidth; static int _nHeight; /*** about_dialog *** Just a wrapper. *********************/ VOID about_dialog(HWND hWndParent) { DialogBox(get_current_hinstance(), MAKEINTRESOURCE(100), hWndParent, dbv_about_dlgproc); } /*****************/ BOOL CALLBACK dbv_about_dlgproc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch ( uMsg ) { /*** Pass these messages to DIB_VIEWER control ***/ case WM_PALETTECHANGED: case WM_QUERYNEWPALETTE: { HWND hWndDib = GetDlgItem(hWndDlg, 100); if ( hWndDib ) SendMessage(hWndDib, uMsg, wParam, lParam); } return TRUE; case WM_TIMER: return dbv_about_ontimer(hWndDlg); case WM_SHOWWINDOW: return dbv_about_onshowwindow(hWndDlg, (BOOL)wParam); case WM_COMMAND: return dbv_about_oncommand(hWndDlg, (UINT)LOWORD(wParam), (UINT)HIWORD(wParam), (HWND)lParam); case WM_INITDIALOG: return dbv_about_oninitdialog(hWndDlg); } return FALSE; } /*** dbv_about_oninitdialog *** Initialize dialog. A little bit tricky. Just assume this function moves some controls around. Take a look at the About Dialog's resource template. *******************************/ static BOOL dbv_about_oninitdialog(HWND hWndDlg) { RECT rcWindow, rcScroller; LPBITMAPINFO lpbmiRes, lpbmiWnd; HGLOBAL hRes; HWND hWndDibCtrl; GetWindowRect(hWndDlg, &rcWindow); /* Control with item nr. 999 is a place holder for our scroller */ GetWindowRect(GetDlgItem(hWndDlg, 999), &rcScroller); /* We got size. Check if our bitmap is available. */ lpbmiRes = (LPBITMAPINFO)LockResource(hRes = LoadResource(get_current_hinstance(), FindResource(get_current_hinstance(), MAKEINTRESOURCE(999), RT_BITMAP))); WINASSERTTEXT(lpbmiRes == NULL, "No #999"); /* Okay, try to create bitmap & scroller */ if ( lpbmiRes ) { if ( NULL != (lpbmiWnd = copy_dib_ptr(lpbmiRes)) && NULL != (hWndDibCtrl = CreateWindowEx(0, DIB_VWR_CLASSNAME, "DIB Scroller", WS_CHILD | WS_VISIBLE | DWS_NOSCROLLBARS, 0, 0, 0, 0, hWndDlg, (HMENU)(int)100, get_current_hinstance(), NULL)) ) { /* Do some asserts */ WINASSERTTEXT(GetParent(hWndDibCtrl) != hWndDlg || hWndDibCtrl != GetDlgItem(hWndDlg, 100), "resource error"); /* Now we need to swap OK button and scroller positions */ MapWindowPoints(HWND_DESKTOP, hWndDlg, (LPPOINT)&rcScroller, sizeof(RECT) / sizeof(POINT)); GetWindowRect(GetDlgItem(hWndDlg, IDOK), &rcWindow); MapWindowPoints(HWND_DESKTOP, hWndDlg, (LPPOINT)&rcWindow, sizeof(RECT) / sizeof(POINT)); /* Move frame & resize frame */ SetWindowPos(GetDlgItem(hWndDlg, 999), 0, rcScroller.left, rcWindow.top, rcScroller.right - rcScroller.left, rcScroller.bottom - rcScroller.top + /* height of button */ rcWindow.bottom - rcWindow.top, SWP_NOREDRAW | SWP_NOZORDER); /* Move OK button */ SetWindowPos(GetDlgItem(hWndDlg, IDOK), 0, rcWindow.left, rcScroller.bottom, 0, 0, SWP_NOREDRAW | SWP_NOZORDER | SWP_NOSIZE); /* Adjust rectangle: actual rectangle of frame in dialog */ GetWindowRect(GetDlgItem(hWndDlg, 999), &rcScroller); MapWindowPoints(HWND_DESKTOP, hWndDlg, (LPPOINT)&rcScroller, sizeof(RECT) / sizeof(POINT)); /* Set rectangle for scroller. Scroller should fit in frame */ #define m_f (3) InflateRect(&rcScroller, m_f * -GetSystemMetrics(SM_CXBORDER), m_f * -GetSystemMetrics(SM_CYBORDER)); #undef m_f /* Move & resize scroller */ SetWindowPos(hWndDibCtrl, 0, rcScroller.left, rcScroller.top, rcScroller.right - rcScroller.left, rcScroller.bottom - rcScroller.top, SWP_NOREDRAW | SWP_NOZORDER); /* Set window DIB bits */ SetBitmapAndPalette(hWndDibCtrl, lpbmiWnd, FALSE); SetScrollWindow(hWndDlg, hWndDibCtrl); /* Set scroll variables */ _nWidth = lpbmiWnd->bmiHeader.biWidth - (rcScroller.right - rcScroller.left); _nHeight = lpbmiWnd->bmiHeader.biHeight - (rcScroller.bottom - rcScroller.top); _nMovX = _nMovY = -1; /* Initialize Snippets rng */ SLongRand(GetTickCount()); return TRUE; } /* If here, error: free resources */ if ( lpbmiWnd ) dib_ptr_free(lpbmiWnd); GlobalUnlock(hRes); } if ( hRes ) FreeResource(hRes); /* We failed! Let's put the scroller place holder out of sight of user. */ SetWindowPos(hWndDlg, 0, 0, 0, rcWindow.right - rcWindow.left, rcScroller.top - rcWindow.top, SWP_NOZORDER | SWP_NOREDRAW | SWP_NOMOVE); return TRUE; } /*** dbv_about_onshowwindow *** Set a timer if this window becomes visible. *******************************/ static BOOL dbv_about_onshowwindow(HWND hWndDlg, BOOL bShow) { /* We're using the user data long as a init. flag */ if ( !IsScrolling(hWndDlg) && bShow ) { SetScrolling(hWndDlg); /* Setup a timer */ if ( GetScrollWindow(hWndDlg) != NULL ) if ( !SetTimer(hWndDlg, ID_TIMER, TIME_OUT, NULL) ) WINASSERTTEXT(TRUE, "Timer failure"); } return FALSE; } /*** dbv_about_on_timer *** Again, a wrapper. ***************************/ static BOOL dbv_about_ontimer(HWND hWndDlg) { HWND hWndDib = GetScrollWindow(hWndDlg); do_scroll(hWndDib, GetDIBData(hWndDib)); return TRUE; } /*** dbv_about_oncommand *** Handler for WM_COMMAND messages. This one responds to IDOK/IDCANCEL only. ****************************/ static BOOL dbv_about_oncommand(HWND hWndDlg, UINT uItemId, UINT uNotification, HWND hWndControl) { /* Unreferenced parameters */ uNotification = uNotification; hWndControl = hWndControl; if ( uItemId == IDOK || uItemId == IDCANCEL ) { KillTimer(hWndDlg, ID_TIMER); RemoveProp(hWndDlg, PROP_SCROLL_HWND); EndDialog(hWndDlg, uItemId); return TRUE; } return FALSE; } /*****************/ static VOID do_scroll(HWND hWndDib, HDIBVWR hdvData) { #define min_step_x (2) #define min_step_y (2) #define max_step_x (4 * GetSystemMetrics(SM_CXBORDER)) #define max_step_y (4 * GetSystemMetrics(SM_CYBORDER)) #define lboundx (0) #define lboundy (0) #define hboundx (_nWidth - 1) #define hboundy (_nHeight - 1) if ( hdvData == NULL ) return; else { int nX = hdvData->nXPos, nY = hdvData->nYPos; #ifdef __SCROLL HDC hdcDib; HBITMAP hbmpDib; #endif nX += _nMovX; nY += _nMovY; /* Check if we hit bounds */ if ( nX < lboundx ) { _nMovX = (int)LongRand() % max_step_x + min_step_x; nX = lboundx + _nMovX; } if ( nY < lboundy ) { _nMovY = (int)LongRand() % max_step_y + min_step_y; nY = lboundy + _nMovY; } if ( nX > hboundx ) { _nMovX = -1 * ((int)LongRand() % max_step_x + min_step_x); nX = hboundx + _nMovX; } if ( nY > hboundy ) { _nMovY = -1 * ((int)LongRand() % max_step_y + min_step_y); nY = hboundy + _nMovY; } #ifdef __SCROLL nDX = nX - hdvData->nXPos; nDY = nY - hdvData->nYPos; #endif /* Directly set the origin in DIB window */ hdvData->nXPos = nX; hdvData->nYPos = nY; #ifndef __SCROLL /* Full redraw might be faster */ InvalidateRect(hWndDib, NULL, FALSE); UpdateWindow(hWndDib); #else GetClientRect(hWndDib, &rcClient); rcScroll = rcClient; OffsetRect(&rcClient, -nDX, -nDY); hrgnResult = CreateRectRgn(1, 1, 1, 1); hrgnClient = CreateRectRgnIndirect(&rcClient); hrgnScroll = CreateRectRgnIndirect(&rcScroll); CombineRgn(hrgnResult, hrgnClient, hrgnScroll, RGN_DIFF); DeleteObject(hrgnClient); DeleteObject(hrgnScroll); ScrollWindowEx(hWndDib, -nDX, -nDY, NULL, NULL, NULL, NULL, SW_INVALIDATE); DeleteObject(hrgnResult); #endif } } /* End of File */