/***************************************************************************** * * Copyright (c) 1999, KL GROUP INC. All Rights Reserved. * http://www.klgroup.com * * This file is provided for demonstration and educational uses only. * Permission to use, copy, modify and distribute this file for * any purpose and without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies, and that the name of KL Group not be used in advertising * or publicity pertaining to this material without the specific, * prior written permission of an authorized representative of * KL Group. * * KL GROUP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. KL GROUP SHALL NOT BE LIABLE FOR ANY * DAMAGES SUFFERED BY USERS AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ #define IN_CASHFLOW_C #ifndef STRICT #define STRICT #endif #include #include #include #include #include "olch2d.h" #include "oc_color.h" #include "flashlbl.h" #include "qrtrdata.h" #include "cashflow.h" #include "pointsty.h" #include "resource.h" /* CashFlow is a simple demo program for Olectra Chart. It displays a bar chart * summarising income and expenses for one quarter. If a bar is clicked with * the mouse, a pie chart is displayed with the details of the data the bar * summarizes - either income from two different sources, or four categories of * expenses - for the appropriate month. When the mouse cursor is passed over a * bar or pie slice in the active window the value is displayed in a Text Area. * * The demo illustrates the initialisation of an XrtData object from the data in * other XrtData objects; uses both the Olectra Chart "convenience macros" for * manipulating XrtData objects (in GetQuarterData()) and accesses the structs * directly elsewhere (e.g. in DisplayFlashLabel()); shows a simple use of * Text Areas; and illustrates the use of XrtPick() and XrtUnpick() in * conjunction with Text Areas. * * New features added for version 6.0 include an axis style for the Y axis of * the bar chart, legend titles, and exploding slices for the pie charts. * * CashFlow uses the following functions and macros in the Olectra Chart API: * - XrtLoadPropertiesFromMemory() * - XrtGetValues() * - XrtSetValues() * - XrtSetNthHeaderString() * - XrtDataCreate() * - XrtDataCreateFromFile() * - XrtDataDestroy() * - XrtDataGetXElement() * - XrtDataSetXElement() * - XrtDataGetYElement() * - XrtDataSetYElement() * - XrtDataGetLastSet() * - XrtDataGetLastPoint() * - XrtTextCreate() * - XrtTextDetail() * - XrtTextDestroy() * - XrtPick() * - XrtUnpick() * * CashFlow was enhanced for version 6.0 to use these new elements of the * Olectra Chart API, which enable the exploding pie slices: * - XrtPointStyleCreate() * - XrtPointStyleGetValues() * - XrtPointStyleSetValues() * - XrtPointStyleDestroy() */ char* Months[] = {"January","February","March","April","May","June","July", "August","September","October","November","December"}; /* Special Y axis for the main chart with a thick, green line with width 4 ticks */ static XrtDataStyle YAxisStyle = { XRT_LPAT_SOLID, XRT_FPAT_SOLID, XrtColorGreen, 2, XRT_POINT_NONE, XrtColorBlack, 4}; /****************************************************************************/ /* WinMain() - Registers CashFlow's classes, creates the Main window that * shows the quarterly summary data, and runs the message pump. */ int WINENTRY WinMain(HINSTANCE hinstCur, HINSTANCE hinstPrev, LPSTR pCmdLine, int nCmdShow) { WNDCLASS wc; MSG msg; HACCEL hAccel; ghinstApp = hinstCur; if (!hinstPrev) { /* Register class for main window. */ wc.style = 0; wc.lpfnWndProc = (WNDPROC)MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = ghinstApp; wc.hIcon = LoadIcon(ghinstApp, "olch2dicon"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = "CashFlowMenu"; wc.lpszClassName = "Main"; if(!RegisterClass(&wc)) { MessageBox(NULL, "RegisterClass() failed.\nUnable to continue.", "CashFlow - WinMain()", MB_OK | MB_ICONEXCLAMATION); return 0; } /* Register class for details windows. */ wc.lpfnWndProc = (WNDPROC)DetailFrameWndProc; wc.lpszMenuName = NULL; wc.cbClsExtra = sizeof(WORD); wc.cbWndExtra = sizeof(HWND); wc.lpszClassName = "Detail"; if(!RegisterClass(&wc)) { MessageBox(NULL, "RegisterClass() failed.\nUnable to continue.", "CashFlow - WinMain()", MB_OK | MB_ICONEXCLAMATION); return 0; } } hAccel = LoadAccelerators(ghinstApp, "CashFlowAccelerators"); /* Create, display, and initialise main window. */ if(!CreateWindow("Main", "Olectra Chart 2D - CashFlow Demo", WS_OVERLAPPEDWINDOW, MAINFRAME_X, MAINFRAME_Y, MAINFRAME_W, MAINFRAME_H, NULL, NULL, ghinstApp, NULL)) { MessageBox(NULL, "CreateWindow() failed.\nUnable to continue.", "CashFlow - WinMain()", MB_OK|MB_ICONEXCLAMATION); return 0; } if(SendMessage(ghwndMain, CFM_INIT, (WPARAM)0, (LPARAM)0) != 0) { MessageBox(NULL,"Failed to initialise main window.\nUnable to continue.", "CashFlow - WinMain()",MB_OK|MB_ICONEXCLAMATION); return 0; } ShowWindow(ghwndMain,nCmdShow); /* Do CashFlow app. */ while(GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(ghwndMain, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return(msg.wParam); } /****************************************************************************/ /* MainWndProc() - Implements the behavior of the main frame window. * It creates the Olectra Chart control that displays the quarterly summary * data and maintains it sized to the main frame's client area. * Instance data is global or static as there can only be one instance * (per process) of this class. */ LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); static HXRT2D hChart = 0; static HWND hwndChart = 0; switch (msg) { case WM_ERASEBKGND: /* Indicate we've erased the background. We haven't, but don't need to as child fills client area. */ return !0; case WM_PALETTECHANGED: case WM_QUERYNEWPALETTE: case WM_SYSCOLORCHANGE: case WM_PALETTEISCHANGING: return SendMessage(hwndChart, msg, wParam, lParam); case WM_SIZE: { RECT rect; GetClientRect(hwnd, &rect); SetWindowPos(hwndChart, HWND_TOP, 0, 0, rect.right, rect.bottom, SWP_NOMOVE|SWP_NOZORDER); } return 0; case WM_COMMAND: // handle commands switch(LOWORD(wParam)) { case IDM_EXIT: DestroyWindow(ghwndMain); //hwnd); break; case IDM_ABOUTDEMO: case IDMHELP: WinHelp(hwnd, "OLCH-DMO.HLP", HELP_CONTEXT, 22); break; case IDM_ABOUTOLECTRACHART: WinHelp(hwnd, "OLCH-DMO.HLP", HELP_CONTEXT, 19); break; case IDM_3D: { BOOL f3dOn; HMENU hmenu; HWND hwndCur; /* Get the current state of the check mark. */ if(!(hmenu = GetMenu(hwnd))) { return 0; } f3dOn = GetMenuState(hmenu, IDM_3D,MF_BYCOMMAND) & MF_CHECKED; /* Tell the summary chart to go to the new 3D state. */ SendMessage(hwndChart, f3dOn ? CFM_3DOFF : CFM_3DON, (WPARAM)0, (LPARAM)0); /* Tell all Detail windows (owned) to go to the new 3D state. */ hwndCur = GetWindow(hwnd, GW_HWNDFIRST); while(hwndCur) { if(GetWindow(hwndCur, GW_OWNER) == hwnd) { SendMessage(hwndCur, f3dOn ? CFM_3DOFF : CFM_3DON, (WPARAM)0, (LPARAM)0); } hwndCur = GetWindow(hwndCur, GW_HWNDNEXT); } /* Set the menu check mark to the new state. */ CheckMenuItem(hmenu, IDM_3D, MF_BYCOMMAND | (f3dOn ? MF_UNCHECKED : MF_CHECKED)); } return 0; } break; case WM_CREATE: /* No cleanup needed on failure - returning -1 causes DestroyWindow() to be called so we get a WM_DESTROY message. */ assert(("CashFlow may have only one Main window per instance.",!ghwndMain)); ghwndMain=hwnd; /* Initialise data for the demo - GetQuarterData() involves some XrtData manipulation. */ if(!(gpQuarterData=GetQuarterData())){ MessageBox(NULL,"Unable to allocate data structures.\nCashFlow will terminate.", "CashFlow - MainWndProc()",MB_OK|MB_ICONEXCLAMATION); return -1; } return 0; case CFM_INIT: { InitInfo initInfo; RECT rect; /* Create the summary chart. */ GetClientRect(hwnd,&rect); if(!(hChart=XrtCreateWindow("", 0,0,rect.right,rect.bottom, hwnd,ghinstApp))){ MessageBox(NULL,"CreateWindow() failed.\nUnable to continue.","CashFlow - MainWndProc()", MB_OK|MB_ICONEXCLAMATION); return -1; } hwndChart = XrtGetWindow(hChart); /* Hook in our summary chart wndproc. */ if(!(initInfo.pfnBaseWndProc = (WNDPROC)SetWindowLong(hwndChart, GWL_WNDPROC, (DWORD)SummaryChartWndProc))) { MessageBox(NULL,"Failed to hook summary chart wndproc.\nUnable to continue.", "CashFlow - MainWndProc()",MB_OK|MB_ICONEXCLAMATION); return -1; } /* Initialise the summary chart using CFM_INIT custom message. */ if(SendMessage(hwndChart, CFM_INIT, (WPARAM)0, (LPARAM)&initInfo) != 0) { MessageBox(NULL,"Failed to initialise summary chart.\nUnable to continue.", "CashFlow - MainWndProc()",MB_OK|MB_ICONEXCLAMATION); return -1; } } return 0; case WM_DESTROY: FreeQuarterData(gpQuarterData); XrtDestroy(hChart); ghwndMain = 0; PostQuitMessage(0); return 0; } return(DefWindowProc(hwnd, msg, wParam, lParam)); } /***************************************************************************/ /* SummaryChartWndProc() - Supplements the behavior of the Olectra Chart * control that shows the quarterly summary data. In particular it displays * the "Flash Labels" that show the value of a bar in the chart when the * mouse cursor is on it, and creates a Detail Frame Window when a bar is * clicked. Instance data is or global as there can only be one instance * (per process) of this class. */ LRESULT CALLBACK SummaryChartWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); POINT pt; RECT rect; static WNDPROC pfnBaseWndProc; XrtPickResult pick; HXRT2D hChart = XrtGetHandle(hwnd); switch(msg) { case WM_MOUSEMOVE: /* If we're not active or mouse cursor is outside window ensure everything's off and do nothing. */ LONG2POINT(lParam, pt); /* Convert mouse coordinates to a POINT struct. */ GetClientRect(hwnd, &rect); if(GetActiveWindow() != ghwndMain || !PT_IN_RECT(pt,rect)) { if(GetCapture() == hwnd) { ReleaseCapture(); RemoveFlashLabel(); /* If there's a flash label up, turn it off. */ } break; } /* We're active and in the window. Make sure capture's on so we know when mouse cursor leaves window. */ if(GetCapture() != hwnd) { SetCapture(hwnd); } /* If we're now in the data ... */ if (XrtPick(hChart, XRT_DATASET1, xPos, yPos, &pick, XRT_XFOCUS|XRT_YFOCUS) == XRT_RGN_IN_GRAPH && (pick.distance == 0)) { DisplayFlashLabel(hChart,pick.set,pick.point); } else { RemoveFlashLabel(); /* If there's a flash label up, turn it off. */ } return 0; case WM_LBUTTONUP: /* If mouse cursor is in a bar, display that bar's details. */ if (XrtPick(hChart, XRT_DATASET1, xPos, yPos, &pick, XRT_XFOCUS|XRT_YFOCUS) == XRT_RGN_IN_GRAPH && (pick.distance == 0)) { InitInfo initInfo; HWND hwndDetailsFrame; char capStr[64]; HMENU hmenu; /* Initialise initInfo for the current bar. */ if (pick.set == INCOME) { initInfo.hXrtData = gpQuarterData->income[pick.point]; } else { initInfo.hXrtData = gpQuarterData->expenses[pick.point]; } initInfo.year = gpQuarterData->year; initInfo.quarter = gpQuarterData->quarter; initInfo.month = pick.point; initInfo.type = pick.set; /* Create details frame window. */ strcpy(capStr, "CashFlow Details - "); strcat(capStr, (initInfo.type == INCOME) ? "Income for " : "Expenses for "); strcat(capStr, Months[initInfo.quarter * MONTHS_PER_QUARTER + initInfo.month]); sprintf(capStr + strlen(capStr), " %u", initInfo.year); if(!(hwndDetailsFrame = CreateWindow("Detail", capStr, WS_OVERLAPPEDWINDOW, 0, 0, DETAILFRAME_W, DETAILFRAME_H, ghwndMain, NULL, ghinstApp, NULL))) { MessageBox(NULL,"CreateWindow() failed.\nUnable to display details.", "CashFlow - SummaryChartWndProc()",MB_OK|MB_ICONEXCLAMATION); break; } /* Initialise the details frame using CFM_INIT custom message. */ if(SendMessage(hwndDetailsFrame,CFM_INIT,(WPARAM)0,(LPARAM)&initInfo) != 0) { MessageBox(NULL,"Failed to initialise window.\nUnable to display details.", "CashFlow - SummaryChartWndProc()",MB_OK|MB_ICONEXCLAMATION); break; } /* Tell it to be 3D if required. */ if(!(hmenu = GetMenu(ghwndMain))) { return 0; } if(GetMenuState(hmenu, IDM_3D, MF_BYCOMMAND) & MF_CHECKED) { SendMessage(hwndDetailsFrame, CFM_3DON, (WPARAM)0, (LPARAM)0); } ShowWindow(hwndDetailsFrame, SW_SHOWNORMAL); } return 0; case CFM_3DON: XrtSetValues( hChart, XRT_GRAPH_DEPTH, (int)BAR_3D_DEPTH, XRT_GRAPH_INCLINATION, (int)BAR_3D_INCLINATION, XRT_GRAPH_ROTATION, (int)BAR_3D_ROTATION, NULL); return 0; case CFM_3DOFF: XrtSetValues( hChart, XRT_GRAPH_DEPTH, (int)0, XRT_GRAPH_INCLINATION, (int)0, XRT_GRAPH_ROTATION, (int)0, NULL); return 0; case CFM_INIT: { int i; XrtDataHandle hXrtData; XrtDataStyle *pDstyle; static COLORREF colors[] = { XrtColorBlack, XrtColorRed }; static char *set_labels[] = { "Income", "Expenses", NULL }; static char *point_labels[] = { "Jan", "Feb", "Mar", NULL }; static char *header[] = { "Cash Flow Summary Q1 1996", NULL }; static char *footer[] = { "Activate window and move mouse cursor into bar to display value.", "Click on bar for details.", NULL }; /* Set the base wndproc. */ pfnBaseWndProc=((InitInfo*)lParam)->pfnBaseWndProc; /* Load the properties. */ XrtSetValues(hChart, XRT_FOOTER_X, 20, XRT_BACKGROUND_COLOR, XrtColorDodgerBlue, XRT_FOREGROUND_COLOR, XrtColorFloralWhite, XRT_TYPE, XRT_TYPE_BAR, XRT_FOOTER_ADJUST, XRT_ADJUST_LEFT, XRT_XANNOTATION_METHOD, XRT_ANNO_POINT_LABELS, XRT_YTITLE, "$", XRT_YAXIS_DATA_STYLE, &YAxisStyle, XRT_SET_LABELS, set_labels, XRT_POINT_LABELS, point_labels, XRT_HEADER_STRINGS, header, XRT_FOOTER_STRINGS, footer, NULL); XrtSetPropString(hChart, XRT_HEADER_FONT, "Times New Roman,18,Bold"); XrtSetPropString(hChart, XRT_FOOTER_FONT, "Times New Roman,10"); XrtSetPropString(hChart, XRT_LEGEND_FONT, "Times New Roman,12"); XrtSetPropString(hChart, XRT_AXIS_FONT, "Times New Roman,12"); for (i=0; i<2; i++) { pDstyle = XrtGetNthDataStyle(hChart, i); pDstyle->color = colors[i]; XrtSetNthDataStyle(hChart, i, pDstyle); } /* Load the data. */ XrtSetValues( hChart, XRT_DATA, gpQuarterData->hSummaryData, NULL); XrtGetValues( hChart, XRT_DATA, &hXrtData, NULL); if(hXrtData != gpQuarterData->hSummaryData){ MessageBox(NULL,"Failed to attach data to summary chart.\nUnable to continue.", "CashFlow - SummaryChartWndProc()",MB_OK|MB_ICONEXCLAMATION); return -1; } } return 0; case WM_DESTROY: RemoveFlashLabel(); /* If there's a flash label up, turn it off. */ break; } assert(("We should never get here w/o having a valid base wndproc.",pfnBaseWndProc)); return CallWindowProc(pfnBaseWndProc, hwnd, msg, wParam, lParam); } /***************************************************************************/ /* DetailFrameWndProc() - Implements the Detail Frame Windows. * These create, and maintain sized in their client area, an Olectra Chart * control displaying a breakdown of the data in one of the Expense or Income * bars in the Summary Chart. Instance data (in this case just the HWND of * the Olectra Chart it contains) is stored in each window's WndExtra member. */ LRESULT CALLBACK DetailFrameWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_ERASEBKGND: /* Indicate we've erased the background. We haven't, but don't need to as child fills client area. */ return !0; case WM_PALETTECHANGED: case WM_QUERYNEWPALETTE: case WM_SYSCOLORCHANGE: case WM_PALETTEISCHANGING: { HWND hwndChart; # ifdef WIN32 if(!(hwndChart = (HWND)GetWindowLong(hwnd,0))) break; # else if(!(hwndChart = (HWND)GetWindowWord(hwnd,0))) break; # endif return SendMessage(hwndChart, msg, wParam, lParam); } case WM_SIZE: { RECT rect; HWND hwndChart; # ifdef WIN32 if(!(hwndChart = (HWND)GetWindowLong(hwnd,0))) break; # else if(!(hwndChart = (HWND)GetWindowWord(hwnd,0))) break; # endif GetClientRect(hwnd, &rect); SetWindowPos(hwndChart, HWND_TOP, 0, 0, rect.right, rect.bottom, SWP_NOMOVE|SWP_NOZORDER); } return 0; case CFM_3DON: { HWND hwndChart; # ifdef WIN32 if(!(hwndChart = (HWND)GetWindowLong(hwnd,0))) break; # else if(!(hwndChart = (HWND)GetWindowWord(hwnd,0))) break; # endif SendMessage(hwndChart, CFM_3DON, (WPARAM)0, (LPARAM)0); } return 0; case CFM_3DOFF: { HWND hwndChart; # ifdef WIN32 if(!(hwndChart = (HWND)GetWindowLong(hwnd,0))) break; # else if(!(hwndChart = (HWND)GetWindowWord(hwnd,0))) break; # endif SendMessage(hwndChart,CFM_3DOFF,(WPARAM)0,(LPARAM)0); } return 0; case WM_CREATE: { unsigned cWindows; /* Position ourself nicely cascaded on siblings. */ cWindows = GetClassWord(hwnd,0); SetClassWord(hwnd,0,(WORD)(cWindows + 1)); SetWindowPos(hwnd,HWND_TOP, (DETAILFRAME_X + cWindows * DETAILFRAME_OFFSET) % GetSystemMetrics(SM_CXSCREEN), (DETAILFRAME_Y + cWindows * DETAILFRAME_OFFSET) % GetSystemMetrics(SM_CYSCREEN), 0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); } return 0; case CFM_INIT: { HXRT2D hChart; HWND hwndChart; InitInfo initInfo; RECT rect; /* Create the details chart. */ GetClientRect(hwnd,&rect); if(!(hChart=XrtCreateWindow("", 0,0,rect.right,rect.bottom, hwnd,ghinstApp))){ DestroyWindow(hwnd); return -1; } hwndChart=XrtGetWindow(hChart); /* Save the HWND of our chart. */ # ifdef WIN32 assert(sizeof(HWND) == sizeof(LONG)); SetWindowLong(hwnd,0,(LONG)hwndChart); # else assert(sizeof(HWND) == sizeof(WORD)); SetWindowWord(hwnd,0,(WORD)hwndChart); # endif /* Initialise chart's initInfo with our initInfo. */ initInfo = *(InitInfo*)lParam; /* Hook in details chart wndproc. */ if(!(initInfo.pfnBaseWndProc=(WNDPROC)SetWindowLong(hwndChart,GWL_WNDPROC,(DWORD)DetailChartWndProc))){ DestroyWindow(hwnd); return -1; } /* Initialise the detail chart using CFM_INIT custom message. */ if(SendMessage(hwndChart,CFM_INIT,(WPARAM)0,(LPARAM)&initInfo) != 0){ DestroyWindow(hwnd); return -1; } } return 0; case WM_DESTROY: { HWND hwndChart; HXRT2D hChart; # ifdef WIN32 if(!(hwndChart = (HWND)GetWindowLong(hwnd,0))) break; # else if(!(hwndChart = (HWND)GetWindowWord(hwnd,0))) break; # endif hChart = XrtGetHandle(hwndChart); XrtDestroy(hChart); } break; } return(DefWindowProc(hwnd, msg, wParam, lParam)); } /***************************************************************************/ /* DetailChartWndProc() - Supplements the behavior of the Olectra Chart * control that shows the details pie chart. In particular it displays the * "Flash Labels" that show the value of a pie slice when the mouse cursor * is on it. Instance data, of which there is currently none would go in * the window's properties. */ LRESULT CALLBACK DetailChartWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); static WNDPROC pfnBaseWndProc; XrtPickResult pick; POINT pt; RECT rect; XrtDataHandle hXrtData; HXRT2D hChart = XrtGetHandle(hwnd); XrtPointStyleHandle hPointStyle; /* New for version 6.0 */ switch(msg) { case WM_MOUSEMOVE: /* If we're not active or mouse cursor is outside window ensure everything's off and do nothing. */ LONG2POINT(lParam, pt); /* Convert mouse coordinates to a POINT struct. */ GetClientRect(hwnd, &rect); if(GetActiveWindow() != GetParent(hwnd) || !PT_IN_RECT(pt,rect)) { if(GetCapture() == hwnd) { ReleaseCapture(); RemoveFlashLabel(); /* If there's a flash label up, turn it off. */ } break; } /* We're active and in the window. Make sure capture's on so we know when mouse cursor leaves window. */ if(GetCapture() != hwnd) { SetCapture(hwnd); } /* If we're now in the data ... */ if (XrtPick(hChart, XRT_DATASET1, xPos, yPos, &pick, XRT_XFOCUS|XRT_YFOCUS) == XRT_RGN_IN_GRAPH && (pick.distance == 0)) { DisplayFlashLabel(hChart,pick.set,pick.point); } else { RemoveFlashLabel(); /* If there's a flash label up, turn it off. */ } return 0; case WM_LBUTTONDOWN: if (XrtPick(hChart, XRT_DATASET1, xPos, yPos, &pick, XRT_XFOCUS|XRT_YFOCUS) == XRT_RGN_IN_LEGEND && (pick.distance == 0)) { /* Get the point style */ hPointStyle = RetrievePointStyle(hChart); if (hPointStyle != NULL) { /* We have a valid pointstyle */ if (pick.set >= 0) { /* We're in a good place */ /* Sets indicate which slice within a specific pie. */ int set; /* Get the current pointstyle position */ XrtPointStyleGetValues( hPointStyle, XRT_POINTSTYLE_SET, &set, NULL ); if (set == pick.set) { /* Re-selected the current slice, so clear the offset by hiding the pointstyle */ XrtPointStyleSetValues( hPointStyle, XRT_POINTSTYLE_SET, HIDDEN_SLICE, NULL); } else { /* Set the pointstyle to apply to the selected slice */ XrtPointStyleSetValues( hPointStyle, XRT_POINTSTYLE_SET, ( pick.set >= 0 ? pick.set : -1 ), NULL); } } } } return 0; case CFM_3DON: XrtSetValues( hChart, XRT_GRAPH_DEPTH, (int)PIE_3D_DEPTH, XRT_GRAPH_INCLINATION, (int)PIE_3D_INCLINATION, NULL); return 0; case CFM_3DOFF: XrtSetValues( hChart, XRT_GRAPH_DEPTH, (int)0, XRT_GRAPH_INCLINATION, (int)0, NULL); return 0; case CFM_INIT: { char str[32]; XrtDataStyle *pDstyle; int i; static COLORREF colors[] = { RGB(0x94,0,0xD3), RGB(0xFF,0xD7,0), RGB(0xFF,0,0), RGB(0,0xFF,0) }; static char *footer[] = { "Activate window and move mouse cursor into pie slice to display value.", "Click legend entry to explode or replace matching slice.", NULL }; /* Set the base wndproc. We only need to do this once. (However, in the unlikely event Olectra Chart is globally * subclassed after this, we will not have the subclass behavior until this app restarts.) */ if(!pfnBaseWndProc) pfnBaseWndProc=((InitInfo*)lParam)->pfnBaseWndProc; /* Load the properties. */ if(((InitInfo*)lParam)->type == INCOME) { static char *labels[] = { "Salary", "Investments", NULL }; XrtSetValues(hChart, XRT_HEADER_FOREGROUND_COLOR, XrtColorBlack, XRT_HEADER_BACKGROUND_COLOR, XrtColorLightCyan, XRT_HEADER_BORDER, XRT_BORDER_PLAIN, XRT_SET_LABELS, labels, XRT_LEGEND_TITLE, "Income", NULL); } else { static char *labels[] = {"Housing", "Auto", "Taxes", "Food", NULL }; XrtSetValues(hChart, XRT_HEADER_FOREGROUND_COLOR, XrtColorRed, XRT_HEADER_BACKGROUND_COLOR, XrtColorLightCyan, XRT_HEADER_BORDER, XRT_BORDER_PLAIN, XRT_SET_LABELS, labels, XRT_LEGEND_TITLE, "Expenses", NULL); } XrtSetValues(hChart, XRT_FOOTER_X, 15, XRT_BACKGROUND_COLOR, XrtColorDodgerBlue, XRT_FOREGROUND_COLOR, XrtColorBlack, XRT_FOOTER_FOREGROUND_COLOR, XrtColorFloralWhite, XRT_TYPE, XRT_TYPE_PIE, XRT_FOOTER_ADJUST, XRT_ADJUST_LEFT, XRT_XANNOTATION_METHOD, XRT_ANNO_POINT_LABELS, XRT_FOOTER_STRINGS, footer, NULL); for (i=0; i<4; i++) { pDstyle = XrtGetNthDataStyle(hChart, i); pDstyle->color = colors[i]; XrtSetNthDataStyle(hChart, i, pDstyle); } XrtSetPropString(hChart, XRT_HEADER_FONT, "Times New Roman,18,Bold"); XrtSetPropString(hChart, XRT_FOOTER_FONT, "Times New Roman,10"); XrtSetPropString(hChart, XRT_LEGEND_FONT, "Times New Roman,14"); XrtSetPropString(hChart, XRT_AXIS_FONT, "Arial,12"); /* Set title */ strcpy(str,(((InitInfo*)lParam)->type == INCOME) ? "Income for " : "Expenses for "); strcat(str,Months[((InitInfo*)lParam)->quarter * MONTHS_PER_QUARTER + ((InitInfo*)lParam)->month]); sprintf(str + strlen(str)," %u",((InitInfo*)lParam)->year); XrtSetNthHeaderString(hChart,0,str); /* Load the data. */ XrtSetValues( hChart, XRT_DATA, ((InitInfo*)lParam)->hXrtData, NULL); XrtGetValues( hChart, XRT_DATA, &hXrtData, NULL); if(hXrtData != ((InitInfo*)lParam)->hXrtData) return -1; /* Create a pointstyle for this chart */ CreatePointStyle(hChart, 20.0); } return 0; case WM_DESTROY: RemoveFlashLabel(); /* If there's a flash label up, turn it off. */ ReleasePointStyle(hChart); /* If there's a pointstyle, release it */ break; } assert(("We should never get here w/o having a valid base wndproc.",pfnBaseWndProc)); return CallWindowProc(pfnBaseWndProc, hwnd, msg, wParam, lParam); } /***************************************************************************************************************************/