README.TXT ========== The DIB Viewer demo application is a Win 4.0 program for viewing DIBs. Introduction ============ This archive contains an implementation of a DIB Viewer control in C. I'ts up to the user (presumably a programmer) of this control to create a viewing application (although DIBVWR.C is an example of how such an application would look like). Because Windows uses DIBs rather heavily, I have used the DIB format to display bitmaps. If you want a AGF (any graphics format) viewer, just make sure you create functions that translate an AG to the Windows DIB/BMP format, and pass the DIB to the DIB window. Used compiler tools =================== A main portion of the source code has been written with Borland C++ 4.02 and Symantec C++ 7.2. The file dibvwr.mk is intended for users of the RSXNTDJ-DJGPP combo. This is a make script which should work with DOS make programs. Tested it with the Borland C++ and Symantec C++ MAKErs only though. If you have the standard RSXNTDJ package, the make file automatically includes headers in the ./include directory. If you're working with the platform SDK headers, you don't need the headers in the include directory. DIBWIN.C, the dib window ======================== DIBWIN.C implements a DIB viewer control. Most of the time you're interfacing with this module. DIBWIN is straightforward; only the set_dib_ptr does some things the complicated way. Unless told otherwise, the dib window destroys the bitmap data upon destruction. If you don't want this, take a look at the Get/SetWindowDiBits functions. To create a dib window you use the CreateWindowXXX API, its class name is defined as DIB_VWR_CLASSNAME defined in DIBWIN.H. The DIBWIN.H header also defines some styles that can be used in the CreateWindowXX call: DWS_NOPALETTE - The dib window won't use palette data when drawing the DIB. DIBs that don't have palettes need to be handled in a special way when displayed in a screen modes with less color capabilities. Currently the dib window can only "quantize" to the 16 and 256 color system palettes (use the SetBitmapAndPalette function). DIBWIN.C is not capable of quantizing to colors in the bit map. Perhaps I'll write special functions for these kind of things in the future. DWS_FITTOCLIENT - Fits the DIB to the client area of the dib window. See the preview window in the dib open dialog for a useful example. Should be used in combination with DWS_NOSCROLLBARS. DWS_NOSCROLLBARS - Doesn't display scrollbars if the client area of the dib window is smaller than the bitmap to be displayed. DWS_NOFASTERASE - By default the dib window by passes the WM_ERASEBACKGROUND and handles both paint and erase logic within the WM_PAINT handler. DIBWIN.C is quite a good demo of how to optimize the paint logic. Here's how DIBVWR.C creates the the dib window: /* We want a DIB_VWR with all default styles on, so we don't specify any of the DWS_xxx styles */ HWND hwndChild = CreateWindowEx(0, DIB_VWR_CLASSNAME, DIB_VWR_CLASSNAME, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hwndDib, (HMENU)ID_DIB_VIEWER, _hInst, NULL); Note that DIBVWR.EXE doesn't need one of the above styles. Try the following combination of styles DWS_NOSCROLLBARS | DWS_FITTOCLIENT. Inter-process sharing of DIBs ----------------------------- There are several ways for processes to share data, e.g. DDE, and clipboard. Under Win32 it's also possible to share memory data between processes. Upon receipt of special messages the dib window creates a DIB in shared memory. The dib window supplies a copy, not the actual DIB it holds, so changing the shared DIB won't change the displayed DIB. However, the dib window returns a read only handle, but with some effort it's possible to write to the shared DIB. (DIBFUNC.C has several "lower level" functions for dealing with shared DIBs.) The dib window creates one shared DIB, which is shared by all processes that requested a shared DIB. A request for a shared DIB just increments a reference count; if a process doesn't need a shared DIB it should clean up the data passed to it. Here the DIBWIN APIs for shared DIBs: ATOM WindowSharedDIBAlloc(HWND hWndDib) Accesses DIB data of a dib window. The returned atom should be used immediately by calling high-level functions in DIBFUNC.C, like copy_shared_dib_atom_ptr (which creates a copy of the shared DIB) or access_shared_dib_atom (which returns the actual pointer to a read only DIB). If you want more control over the shared DIB, there are a bunch of other functions for accessing the shared dib. If the function returns 0, an error occurred somewhere. The returned atom should be freed by a call to WindowSharedDIBFree. Don't free the atom yourself by calling GlobalDeleteAtom. BOOL WindowSharedDIBFree(HWND hWndDib, ATOM hAtom) This function should be called immediately after using the ATOM returned by WindowSharedDibFree. If you want your application to share DIBs without using the dib window you should really take a look at the other shared DIB functions of DIBFUNC.C. It's a kinda neat implementation. Setting and getting bitmaps and palettes ---------------------------------------- Within the same application you can set the displayed DIB by using another set of WINDIB APIs. The DIB window accepts DIBs in two forms: - handles. Under Win 16 DIBs were allocated from the global heap through functions that return handles to allocated data. Under Win32 you can use plain pointers to memory allocated through the more powerful heap allocation functions. If you don't want the dib window to be the owner of a passed handle, you should free the handle by calling GlobalFree yourself. This includes **copies** of handles returned by GetWindowDIBits with the flags SWD_HANDLE | SWD_COPY! Here's an example: // Get a handle copy of the DIB stored by the DIB Window hglbDib = (HGLOBAL)GetWindowDIBits(hWndDib, SWD_HANDLE | SWD_COPY); // Get a pointer to DIB data lpbmi = (LPBITMAPINFO)GlobalLock(hglbDib); // ... Do something with the DIB // Unlock data GlobalUnlock(hglbDib); // Free the copy by calling GlobalFree GlobalFree(hglbDib); - pointers. Internally the dib window stores the displayed dib as a pointer to actual DIB data. The actual DIB data has been allocated through a call to a heap allocation function, from the current process. If you need a clean new DIB, use the dib_ptr_alloc function (see DIBFUNC.C). A dib_ptr_alloc'ed DIB should be freed with dib_ptr_free, unless you passed it to a DIB window and the DIB window should be the owner. If you have a requested a copy of a DIB (GetWindowDIBits with flag SWD_COPY), you need to free it with dib_ptr_free. Here's an example of how to use a returned *copy* of a DIB: lpbmi = (LPBITMAPINFO)GetWindowDIBits(hWndDib, SWD_COPY); /* Do something with the DIB */ /* It's a copy, so we need to free this with HeapFree */ dib_ptr_free(lpbmi); The dib window automatically deallocates any associated memory objects: DIBs, palettes, shared DIBs. If you don't want this, use the Set/GetWindowDIBits to create copies of DIBs. BOOL SetWindowDIBits(HWND hWndDib, LPVOID lpdib, UINT uFlags) LPVOID GetWindowDIBits(HWND hWndDib, UINT uFlags) These two functions accept/return pointers or handles to DIBs. The flags parameters tell how the dib window should accept/return data. Although WINDIB.H defines different constants for both functions, you can use the SWD_XXX constants for the GetWindowDIBits function. At least, to some extent: some SWD_XXX constants are meaningful to the SetWindowDIBits function only. You can combine the constants by OR'ing them. Use SWD_COPY | SWD_HANDLE if you want the dib window to create a copy of a passed handle to SetWindowDIBits. Here the constants: SWD_HANDLE, GWD_HANDLE - The LPVOID parameter of SetWindowDIBits should contain a global handle (allocated with GlobalAlloc) to a DIB. If you GlobalLock a dib handle, you get a pointer to the DIB. GetWindowDIBits returns the handle to a dib. Mainly for use in DDE or with old Windows applications. If you don't specify this flag, the dib window expects/ returns a pointer to a DIB allocated on the heap (through dib_alloc_ptr). SWD_COPY - Tells both functions to create a copy of bitmap data. In the case of SetWindowDIBits, the dib window creates a copy of the parameter passed through the LPVOID parameter (by default a pointer to a DIB). If used in GetWindowDIBits, the dib window creates a copy of the DIB it contains. SWD_REDRAW - Forces an update of the Window. Only meaningful with SetWindowDIBits. SWD_DONTDELETEPREV - If you set a DIB with this style OR-ed, the dib window won't delete/destroy the previous DIB. Get the previous DIB by calling GetWindowDIBits without the SWD_COPY or GWD_COPY flag specified! Note: if the dib window has one, SetWindowDIBits also destroys the palette, UNLESS you specified the SWD_DONTDELETE flag. If this flag is used the palette won't get destroyed, too. If you use SWD_DONTDELETE, use it wisely. Both functions accept 0 (zero) as a flag. In that case SetWindowDIBits requires a DIB allocated with HeapAlloc; GetWindowDIBits returns the actual DIB used by the dib window. There are also functions that deal with setting and getting palettes: BOOL SetWindowDIBPalette (HWND, HPALETTE, UINT); HPALETTE GetWindowDIBPalette (HWND); Note that GetWindowDIBPalette does not accept flags. If you need to copy a palette, check out the copy_palette function in DIBFUNC.C. The flags for SetWindowDIBPalette are: SWDP_REDRAW - Forces a redraw of the dib window. SWDP_DONTDELETE - Doesn't delete the previous palette. Before you call SetWindowDIBPalette with this flag, make sure you know the handle of the previous palette! Then there's a function for automatically setting a palette and a bitmap. It's actually a simple wrapper around the previous function. VOID SetBitmapAndPalette (HWND, LPBITMAPINFO, BOOL); The second parameter is the DIB. The Window will be the owner of the DIB; the DIB must be allocated through a call with HeapAlloc. Translating other graphics formats ================================== For translating other graphics formats to images viewable inside a DIB window you need to keep these things in mind: 1. You need to translate the graphics to the DIB format. 2. Use the dib_ptr_alloc to create empty bitmaps. Although dib_ptr_alloc also accepts BITMAPINFO structs with only a valid BITMAPINFOHEADER structure. 3. The DIBWIN.C module only quantizes colors to the system palette(s) if you have images with more than 256 colors Demo application ================ The demo application shows how to use DIBWIN.C within an application. Legal statements ================ The author (Alfons Hoogervorst) nor any of the in this file mentioned persons and/or companies can be held responsible/liable for damages resulting of incorrect use/working of the described software. This software is provided AS IS: you the user (presumeably a programmer) take all responsibility in using the software/source code. You're free to use the files for whatever purpose. Trademarks statements --------------------- In case I inadvertently mentioned a trademark without explicitly referring to its holder: all implictly mentioned trademark phrases are explicit to be mentioned trademarks of their implicitly mentioned but explicitly to be mentioned explicit implicit holders. Other notes =========== Author ------ Alfons Hoogervorst works as free-lancer and has been programming Windows for quite a long time. He specializes in low-level, custom control and WinHelp programming. He can be contacted at proteus@worldaccess.nl, alternatively try a.hoogervorst@inter.nl.net.