|
|
/* r
* CSVPick.C * * Picker wizard for CSV import/export * * Copyright 1997 Microsoft Corporation. All Rights Reserved. */
#include "_comctl.h"
#include <windows.h>
#include <commctrl.h>
#include <mapix.h>
#include <wab.h>
#include <wabguid.h>
#include <wabdbg.h>
#include <wabmig.h>
#include <emsabtag.h>
#include "wabimp.h"
#include "..\..\wab32res\resrc2.h"
#include "dbgutil.h"
#include <shlwapi.h>
const TCHAR szCSVFilter[] = "*.csv"; const TCHAR szCSVExt[] = "csv";
#define CHECK_BITMAP_WIDTH 16
typedef struct { LPPROP_NAME rgPropNames; LPPROP_NAME * lppImportMapping; LPHANDLE lphFile; LPULONG lpcFields; LPTSTR szSep; } PROPSHEET_DATA, * LPPROPSHEET_DATA;
TCHAR szCSVFileName[MAX_PATH + 1] = "";
INT_PTR CALLBACK ExportPickFieldsPageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ExportFilePageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ImportFilePageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ImportMapFieldsPageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ChangeMappingDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
/***************************************************************************
Name : FillInPropertyPage
Purpose : Fills in the given PROPSHEETPAGE structure
Parameters: psp -> property sheet page structure idDlg = dialog id pszProc = title for page pfnDlgProc -> Dialog procedure lParam = application specified data
Returns : none
Comment : This function fills in a PROPSHEETPAGE structure with the information the system needs to create the page.
***************************************************************************/ void FillInPropertyPage(PROPSHEETPAGE* psp, int idDlg, LPSTR pszProc, DLGPROC pfnDlgProc, LPARAM lParam) { psp->dwSize = sizeof(PROPSHEETPAGE); psp->dwFlags = 0; psp->hInstance = hInst; psp->pszTemplate = MAKEINTRESOURCE(idDlg); psp->pszIcon = NULL; psp->pfnDlgProc = pfnDlgProc; psp->pszTitle = pszProc; psp->lParam = lParam; }
/***************************************************************************
Name : HandleCheckMark
Purpose : Deals with setting the checkmark for a particular item in the listview.
Parameters: hwndLV = ListView handle iItem = index of item to set rgTable = PROP_NAME table
Returns : none
Comment :
***************************************************************************/ void HandleCheckMark(HWND hWndLV, ULONG iItem, LPPROP_NAME rgTable) { // Locals
LV_ITEM lvi;
// Clear it
ZeroMemory(&lvi, sizeof(LV_ITEM)); lvi.mask = LVIF_PARAM; lvi.iItem = iItem; ListView_GetItem(hWndLV, &lvi); rgTable[lvi.iItem].fChosen = ! rgTable[lvi.iItem].fChosen;
ZeroMemory(&lvi, sizeof(LV_ITEM)); lvi.mask = LVIF_STATE; lvi.iItem = iItem; lvi.state = rgTable[iItem].fChosen ? INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1) : INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1);
lvi.stateMask = LVIS_STATEIMAGEMASK; ListView_SetItem(hWndLV, &lvi); }
/***************************************************************************
Name : HandleMultipleCheckMarks
Purpose : Deals with setting the checkmark for a bunch of selected items in the list view - basically sets every selected item to the toggled state of the first item in the selection
Parameters: hwndLV = ListView handle rgTable = LPPROP_NAME table
Returns : none
Comment :
***************************************************************************/ void HandleMultipleCheckMarks(HWND hWndLV, LPPROP_NAME rgTable) { // Locals
LV_ITEM lvi; int nIndex = 0; BOOL fState = FALSE;
// get the index of the first item
nIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED);
// toggle this item
HandleCheckMark(hWndLV, nIndex, rgTable);
fState = rgTable[nIndex].fChosen;
while((nIndex = ListView_GetNextItem(hWndLV, nIndex, LVNI_SELECTED)) >= 0) { // Set all the other selected items to the same state
rgTable[nIndex].fChosen = fState;
ZeroMemory(&lvi, sizeof(LV_ITEM)); lvi.mask = LVIF_STATE; lvi.iItem = nIndex; lvi.state = rgTable[nIndex].fChosen ? INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1) : INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1);
lvi.stateMask = LVIS_STATEIMAGEMASK; ListView_SetItem(hWndLV, &lvi); } return; }
/***************************************************************************
Name : ExportWizard
Purpose : Present the Export Wizard
Parameters: hwnd = parent window handle szFileName -> filename buffer (MAX_PATH + 1, please) rgPropNames -> property name list
Returns : HRESULT
Comment :
***************************************************************************/ HRESULT ExportWizard(HWND hWnd, LPTSTR szFileName, ULONG cchSize, LPPROP_NAME rgPropNames) { HRESULT hResult = hrSuccess; PROPSHEETPAGE psp[NUM_EXPORT_WIZARD_PAGES]; PROPSHEETHEADER psh;
FillInPropertyPage(&psp[0], IDD_CSV_EXPORT_WIZARD_FILE, NULL, ExportFilePageProc, 0); FillInPropertyPage(&psp[1], IDD_CSV_EXPORT_WIZARD_PICK, NULL, ExportPickFieldsPageProc, 0);
psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW | PSH_USEICONID; psh.hwndParent = hWnd; psh.pszCaption = NULL; psh.pszIcon = MAKEINTRESOURCE(IDI_WabMig); psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); psh.ppsp = (LPCPROPSHEETPAGE) &psp;
psh.hIcon = NULL; psh.hInstance = hInst; psh.nStartPage = 0; psh.pStartPage = NULL;
switch (PropertySheet(&psh)) { case -1: hResult = ResultFromScode(MAPI_E_CALL_FAILED); DebugTrace("PropertySheet failed -> %u\n", GetLastError()); Assert(FALSE); break; case 0: hResult = ResultFromScode(MAPI_E_USER_CANCEL); DebugTrace("PropertySheet cancelled by user\n"); break; default: StrCpyN(szFileName, szCSVFileName, cchSize); break; }
return(hResult); }
/***************************************************************************
Name : ImportWizard
Purpose : Present the CSV Import Wizard
Parameters: hwnd = parent window handle szFileName -> filename buffer (MAX_PATH + 1, please) rgPropNames -> property name list szSep -> list separator lppImportMapping -> returned property mapping table lpcFields -> returned size of property mapping table lphFile -> returned file handle to CSV file with header row already parsed out.
Returns : HRESULT
Comment :
***************************************************************************/ HRESULT ImportWizard(HWND hWnd, LPTSTR szFileName, ULONG cchSize, LPPROP_NAME rgPropNames, LPTSTR szSep, LPPROP_NAME * lppImportMapping, LPULONG lpcFields, LPHANDLE lphFile) { HRESULT hResult = hrSuccess; PROPSHEETPAGE psp[NUM_IMPORT_WIZARD_PAGES]; PROPSHEETHEADER psh; PROPSHEET_DATA pd;
pd.rgPropNames = rgPropNames; pd.lppImportMapping = lppImportMapping; pd.lphFile = lphFile; pd.lpcFields = lpcFields; pd.szSep = szSep;
FillInPropertyPage(&psp[0], IDD_CSV_IMPORT_WIZARD_FILE, NULL, ImportFilePageProc, (LPARAM)&pd); FillInPropertyPage(&psp[1], IDD_CSV_IMPORT_WIZARD_MAP, NULL, ImportMapFieldsPageProc, (LPARAM)&pd);
psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW | PSH_USEICONID; psh.hwndParent = hWnd; psh.pszCaption = NULL; psh.pszIcon = MAKEINTRESOURCE(IDI_WabMig); psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); psh.ppsp = (LPCPROPSHEETPAGE) &psp;
psh.hIcon = NULL; psh.hInstance = hInst; psh.nStartPage = 0; psh.pStartPage = NULL;
switch (PropertySheet(&psh)) { case -1: hResult = ResultFromScode(MAPI_E_CALL_FAILED); DebugTrace("PropertySheet failed -> %u\n", GetLastError()); Assert(FALSE); break; case 0: hResult = ResultFromScode(MAPI_E_USER_CANCEL); DebugTrace("PropertySheet cancelled by user\n"); break; default: StrCpyN(szFileName, szCSVFileName, cchSize); break; }
return(hResult); }
/***************************************************************************
Name : ExportFilePageProc
Purpose : Process messages for "Export Filename" page
Parameters: standard window proc parameters
Returns : standard window proc return
Messages : WM_INITDIALOG - intializes the page WM_NOTIFY - processes the notifications sent to the page
Comment :
***************************************************************************/ INT_PTR CALLBACK ExportFilePageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static TCHAR szTempFileName[MAX_PATH + 1] = "";
switch (message) { case WM_INITDIALOG: StrCpyN(szTempFileName, szCSVFileName, ARRAYSIZE(szTempFileName)); break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_BROWSE: SendDlgItemMessage(hDlg, IDE_CSV_EXPORT_NAME, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)szTempFileName); SaveFileDialog(hDlg, szTempFileName, szCSVFilter, IDS_CSV_FILE_SPEC, szTextFilter, IDS_TEXT_FILE_SPEC, szAllFilter, IDS_ALL_FILE_SPEC, szCSVExt, OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, hInst, 0, // idsTitle
0); // idsSaveButton
PropSheet_SetWizButtons(GetParent(hDlg), szTempFileName[0] ? PSWIZB_NEXT : 0); SendMessage(GetDlgItem(hDlg, IDE_CSV_EXPORT_NAME), WM_SETTEXT, 0, (LPARAM)szTempFileName); break;
case IDE_CSV_EXPORT_NAME: switch (HIWORD(wParam)) { // notification code
case EN_CHANGE: SendDlgItemMessage(hDlg, IDE_CSV_EXPORT_NAME, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)szTempFileName); if ((ULONG)LOWORD(wParam) == IDE_CSV_EXPORT_NAME) { PropSheet_SetWizButtons(GetParent(hDlg), szTempFileName[0] ? PSWIZB_NEXT : 0); } break; } break; } break;
case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); return(1);
case PSN_RESET: // reset to the original values
StrCpyN(szTempFileName, szCSVFileName, ARRAYSIZE(szTempFileName)); SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); break;
case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hDlg), szTempFileName[0] ? PSWIZB_NEXT : 0); SendMessage(GetDlgItem(hDlg, IDE_CSV_EXPORT_NAME), WM_SETTEXT, 0, (LPARAM)szTempFileName); break;
case PSN_WIZNEXT: // the Next button was pressed
SendDlgItemMessage(hDlg, IDE_CSV_EXPORT_NAME, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)szTempFileName); StrCpyN(szCSVFileName, szTempFileName, ARRAYSIZE(szCSVFileName)); break;
default: return(FALSE); } break;
default: return(FALSE); } return(TRUE); }
/***************************************************************************
Name : ExportPickFieldsPageProc
Purpose : Process messages for "Pick Fields" page
Parameters: standard window proc parameters
Returns : standard window proc return
Messages : WM_INITDIALOG - intializes the page WM_NOTIFY - processes the notifications sent to the page
Comment :
***************************************************************************/ INT_PTR CALLBACK ExportPickFieldsPageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND hWndLV; HIMAGELIST himl; LV_ITEM lvi; LV_COLUMN lvm; LV_HITTESTINFO lvh; POINT point; ULONG i, nIndex; NMHDR * pnmhdr; RECT rect;
switch (message) { case WM_INITDIALOG: // Ensure that the common control DLL is loaded.
InitCommonControls();
// List view hwnd
hWndLV = GetDlgItem(hDlg, IDLV_PICKER);
// Load Image List for list view
if (himl = ImageList_LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CHECKS), 16, 0, RGB(128, 0, 128))) { ListView_SetImageList(hWndLV, himl, LVSIL_STATE); }
// Fill the listview
ZeroMemory(&lvi, sizeof(LV_ITEM)); lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
for (i = 0; i < NUM_EXPORT_PROPS; i++) { lvi.iItem = i; lvi.pszText = rgPropNames[i].lpszName; lvi.cchTextMax = lstrlen(lvi.pszText); lvi.lParam = (LPARAM)&rgPropNames[i]; lvi.state = rgPropNames[i].fChosen ? INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1) : INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1); lvi.stateMask = LVIS_STATEIMAGEMASK;
if (ListView_InsertItem(hWndLV, &lvi) == -1) { DebugTrace("ListView_InsertItem -> %u\n", GetLastError()); Assert(FALSE); } }
// Insert a column for the text
// We don't have a header, so we don't need to set the text.
ZeroMemory(&lvm, sizeof(LV_COLUMN)); lvm.mask = LVCF_WIDTH; // set the column width to the size of our listbox.
GetClientRect(hWndLV, &rect); lvm.cx = rect.right; ListView_InsertColumn(hWndLV, 0, &lvm);
// Full row selection on listview
ListView_SetExtendedListViewStyle(hWndLV, LVS_EX_FULLROWSELECT);
// Select the first item in the list
ListView_SetItemState( hWndLV, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
return(1);
case WM_COMMAND: return(TRUE); break;
case WM_NOTIFY: pnmhdr = (LPNMHDR)lParam;
switch (((NMHDR FAR *)lParam)->code) { case NM_CLICK: case NM_DBLCLK: hWndLV = GetDlgItem(hDlg, IDLV_PICKER);
i = GetMessagePos(); point.x = LOWORD(i); point.y = HIWORD(i); ScreenToClient(hWndLV, &point); lvh.pt = point; nIndex = ListView_HitTest(hWndLV, &lvh); // if single click on icon or double click anywhere, toggle the checkmark.
if (((NMHDR FAR *)lParam)->code == NM_DBLCLK || ( (lvh.flags & LVHT_ONITEMSTATEICON) && !(lvh.flags & LVHT_ONITEMLABEL))) { HandleCheckMark(hWndLV, nIndex, rgPropNames); } break;
case LVN_KEYDOWN: hWndLV = GetDlgItem(hDlg, IDLV_PICKER);
// toggle checkmark if SPACE key is pressed
if (pnmhdr->hwndFrom == hWndLV) { LV_KEYDOWN *pnkd = (LV_KEYDOWN *)lParam; // BUG 25097 allow multiple select
if (pnkd->wVKey == VK_SPACE) { nIndex = ListView_GetSelectedCount(hWndLV); if(nIndex == 1) { nIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED | LVNI_ALL); //if (nIndex >= 0) {
HandleCheckMark(hWndLV, nIndex, rgPropNames); //}
} else if(nIndex > 1) { //multiple select case ...
// Toggle all the selected items to the same state as the
// first item ...
HandleMultipleCheckMarks(hWndLV, rgPropNames); } } } break;
case PSN_KILLACTIVE: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); return(1); break;
case PSN_RESET: // rest to the original values
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); break;
case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH); break;
case PSN_WIZBACK: break;
case PSN_WIZFINISH: // Here's where we do the export
break;
default: return(FALSE); } break;
default: return(FALSE); } return(TRUE); }
//$$/////////////////////////////////////////////////////////////////////////////
//
// my_atoi - personal version of atoi function
//
// lpsz - string to parse into numbers - non numeral characters are ignored
//
/////////////////////////////////////////////////////////////////////////////////
int my_atoi(LPTSTR lpsz) { int i=0; int nValue = 0;
if(lpsz) { if (lstrlen(lpsz)) { nValue = 0; while((lpsz[i]!='\0')&&(i<=lstrlen(lpsz))) { int tmp = lpsz[i]-'0'; if(tmp <= 9) nValue = nValue*10 + tmp; i++; } } }
return nValue; }
typedef struct { LPTSTR lpszName; ULONG iPropNamesTable; // index in rgProp
} SYNONYM, *LPSYNONYM;
/***************************************************************************
Name : FindPropName
Purpose : Finds a property name in the prop name table
Parameters: lpName = name to find or NULL to free the static synonym table rgPropNames = property name table ulcPropNames = size of property name table
Returns : index into table or INDEX_NOT_FOUND
Comment :
***************************************************************************/ #define INDEX_NOT_FOUND 0xFFFFFFFF
ULONG FindPropName(PUCHAR lpName, LPPROP_NAME rgPropNames, ULONG ulcPropNames) { ULONG i; static LPSYNONYM lpSynonymTable = NULL; static ULONG ulSynonymsSave = 0; ULONG ulSynonyms = ulSynonymsSave; // Keep local copy for compiler bug
ULONG ulSynonymStrings = 0;
if (lpName == NULL) { goto clean_table; }
for (i = 0; i < ulcPropNames; i++) { if (! rgPropNames[i].fChosen) { // Don't re-use props!
if (! lstrcmpi(lpName, rgPropNames[i].lpszName)) { return(i); } } }
// If it wasn't found, look it up in the synonym table resource
// First, make sure we have a synonym table loaded
if (! lpSynonymTable) { TCHAR szBuffer[MAX_RESOURCE_STRING + 1]; LPTSTR lpSynonym, lpName; ULONG j;
// Load the synonym table
if (LoadString(hInst, idsSynonymCount, szBuffer, sizeof(szBuffer))) { DebugTrace("Loading synonym table, %s synonyms\n", szBuffer); ulSynonymStrings = my_atoi(szBuffer);
if (ulSynonymStrings) { // Allocate the synonym table
if (! (lpSynonymTable = LocalAlloc(LPTR, ulSynonymStrings * sizeof(SYNONYM)))) { DebugTrace("LocalAlloc synonym table -> %u\n", GetLastError()); goto clean_table; }
for (i = 0; i < ulSynonymStrings; i++) { if (LoadString(hInst, idsSynonym001 + i, // ids of synonym string
szBuffer, sizeof(szBuffer))) { // Split the string at the '=' character
lpSynonym = lpName = szBuffer; while (*lpName) { if (*lpName == '=') { // found equal sign, break the string here
*(lpName++) = '\0'; break; } lpName = CharNext(lpName); }
// Find the name specified
for (j = 0; j < ulcPropNames; j++) { if (! lstrcmpi(lpName, rgPropNames[j].lpszName)) { // Found it
// Allocate a buffer for the synonym string
Assert(ulSynonyms < ulSynonymStrings); if (! (lpSynonymTable[ulSynonyms].lpszName = LocalAlloc(LPTR, lstrlen(lpSynonym) + 1))) { DebugTrace("LocalAlloc in synonym table -> %u\n", GetLastError()); goto clean_table; } StrCpyN(lpSynonymTable[ulSynonyms].lpszName, lpSynonym, lstrlen(lpSynonym) + 1); lpSynonymTable[ulSynonyms].iPropNamesTable = j; ulSynonyms++; break; } } } } } } ulSynonymsSave = ulSynonyms; }
if (lpSynonymTable) { // Find it
for (i = 0; i < ulSynonyms; i++) { if (! lstrcmpi(lpName, lpSynonymTable[i].lpszName)) { // Found the name. Is it already used?
if (rgPropNames[lpSynonymTable[i].iPropNamesTable].fChosen) { break; // Found, but already used
}
return(lpSynonymTable[i].iPropNamesTable); } } }
exit: return(INDEX_NOT_FOUND);
clean_table: if (lpSynonymTable) { for (i = 0; i < ulSynonyms; i++) { if (lpSynonymTable[i].lpszName) { LocalFree(lpSynonymTable[i].lpszName); } } LocalFree(lpSynonymTable); lpSynonymTable = NULL; ulSynonymsSave = 0; } goto exit; }
/***************************************************************************
Name : BuildCSVTable
Purpose : Builds the initial CSV mapping table from the file header.
Parameters: lpFileName = filename to test rgPropnames = property name table szSep = separator character lppImportMapping -> returned mapping table lpcFields -> returned size of import mapping table lphFile -> returned file handle for CSV file. File pointer will be set past the header row.
Returns : HRESULT
Comment :
***************************************************************************/ HRESULT BuildCSVTable(LPTSTR lpFileName, LPPROP_NAME rgPropNames, LPTSTR szSep, LPPROP_NAME * lppImportMapping, LPULONG lpcFields, LPHANDLE lphFile) { PUCHAR * rgItems = NULL; ULONG i, ulcItems = 0; LPPROP_NAME rgImportMapping = NULL; HRESULT hResult; ULONG ulPropIndex;
// Open the file
if ((*lphFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)) == INVALID_HANDLE_VALUE) { DebugTrace("Couldn't open file %s -> %u\n", lpFileName, GetLastError()); return(ResultFromScode(MAPI_E_NOT_FOUND)); }
// Parse the first row
if (hResult = ReadCSVLine(*lphFile, szSep, &ulcItems, &rgItems)) { DebugTrace("Couldn't read the CSV header\n"); goto exit; }
// Allocate the table
if (! (*lppImportMapping = rgImportMapping = LocalAlloc(LPTR, ulcItems * sizeof(PROP_NAME)))) { DebugTrace("Allocation of import mapping table -> %u\n", GetLastError()); hResult = ResultFromScode(MAPI_E_NOT_ENOUGH_MEMORY); goto exit; }
// Reset flags on WAB property table
for (i = 0; i < NUM_EXPORT_PROPS; i++) { rgPropNames[i].fChosen = FALSE; }
// Fill in the CSV fields
for (i = 0; i < ulcItems; i++) { Assert(rgItems[i]);
if (rgItems[i] && *rgItems[i]) { rgImportMapping[i].lpszCSVName = rgItems[i];
// Look it up in the WAB property names table
if (INDEX_NOT_FOUND != (ulPropIndex = FindPropName(rgItems[i], rgPropNames, NUM_EXPORT_PROPS))) { // Found a match
rgImportMapping[i].lpszName = rgPropNames[ulPropIndex].lpszName; rgImportMapping[i].ids = rgPropNames[ulPropIndex].ids; rgImportMapping[i].fChosen = TRUE; rgImportMapping[i].ulPropTag = rgPropNames[ulPropIndex].ulPropTag; rgPropNames[ulPropIndex].fChosen = TRUE; DebugTrace("Match %u: %s\n", i, rgItems[i]); } else { DebugTrace("Unknown %u: %s\n", i, rgItems[i]); } } else { DebugTrace("Empty %u: %s\n", i, rgItems[i]); } }
*lpcFields = ulcItems;
exit: if (hResult) { if (*lphFile != INVALID_HANDLE_VALUE) { CloseHandle(*lphFile); *lphFile = INVALID_HANDLE_VALUE; }
if (rgItems) { for (i = 0; i < ulcItems; i++) { if (rgItems[i]) { LocalFree(rgItems[i]); } } }
if (rgImportMapping) { LocalFree(rgImportMapping); *lppImportMapping = NULL; } }
// If no error, leave the item strings since they are part of the mapping table.
if (rgItems) { LocalFree(rgItems); }
// Free the static memory for the synonym table.
FindPropName(NULL, rgPropNames, NUM_EXPORT_PROPS); return(hResult); }
/***************************************************************************
Name : FileExists
Purpose : Tests for existence of a file
Parameters: lpFileName = filename to test
Returns : TRUE if the file exists
Comment :
***************************************************************************/ BOOL FileExists(LPTSTR lpFileName) { DWORD dwRet;
if ((dwRet = GetFileAttributes(lpFileName)) == 0xFFFFFFFF) { return(FALSE); } else { return(! (dwRet & FILE_ATTRIBUTE_DIRECTORY)); // file was found
} }
/***************************************************************************
Name : ImportFilePageProc
Purpose : Process messages for "Import Filename" page
Parameters: standard window proc parameters
Returns : standard window proc return
Messages : WM_INITDIALOG - intializes the page WM_NOTIFY - processes the notifications sent to the page
Comment :
***************************************************************************/ INT_PTR CALLBACK ImportFilePageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static TCHAR szTempFileName[MAX_PATH + 1] = ""; static LPPROPSHEET_DATA lppd = NULL; LPPROPSHEETPAGE lppsp;
switch (message) { case WM_INITDIALOG: StrCpyN(szTempFileName, szCSVFileName, ARRAYSIZE(szTempFileName)); lppsp = (LPPROPSHEETPAGE)lParam; lppd = (LPPROPSHEET_DATA)lppsp->lParam; break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_BROWSE: SendDlgItemMessage(hDlg, IDE_CSV_IMPORT_NAME, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)szTempFileName); OpenFileDialog(hDlg, szTempFileName, szCSVFilter, IDS_CSV_FILE_SPEC, szTextFilter, IDS_TEXT_FILE_SPEC, szAllFilter, IDS_ALL_FILE_SPEC, szCSVExt, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST, hInst, 0, //idsTitle
0); // idsSaveButton
PropSheet_SetWizButtons(GetParent(hDlg), FileExists(szTempFileName) ? PSWIZB_NEXT : 0); SendMessage(GetDlgItem(hDlg, IDE_CSV_IMPORT_NAME), WM_SETTEXT, 0, (LPARAM)szTempFileName); break;
case IDE_CSV_IMPORT_NAME: switch (HIWORD(wParam)) { // notification code
case EN_CHANGE: SendDlgItemMessage(hDlg, IDE_CSV_IMPORT_NAME, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)szTempFileName); if ((ULONG)LOWORD(wParam) == IDE_CSV_IMPORT_NAME) { PropSheet_SetWizButtons(GetParent(hDlg), FileExists(szTempFileName) ? PSWIZB_NEXT : 0); } break; } break; } break;
case WM_NOTIFY: switch (((NMHDR FAR *) lParam)->code) { case PSN_KILLACTIVE: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); return(1);
case PSN_RESET: // reset to the original values
StrCpyN(szTempFileName, szCSVFileName, ARRAYSIZE(szTempFileName)); SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); break;
case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hDlg), szTempFileName[0] ? PSWIZB_NEXT : 0); SendMessage(GetDlgItem(hDlg, IDE_CSV_IMPORT_NAME), WM_SETTEXT, 0, (LPARAM)szTempFileName); break;
case PSN_WIZNEXT: // the Next button was pressed
SendDlgItemMessage(hDlg, IDE_CSV_IMPORT_NAME, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)szTempFileName); StrCpyN(szCSVFileName, szTempFileName, ARRAYSIZE(szCSVFileName)); break;
default: return(FALSE); } break;
default: return(FALSE); } return(TRUE); }
typedef struct { LPPROP_NAME lpMapping; LPPROP_NAME rgPropNames; ULONG ulcPropNames; ULONG ulColumn; } CHANGE_MAPPING_INFO, * LPCHANGE_MAPPING_INFO;
void HandleChangeMapping(HWND hDlg, LPPROPSHEET_DATA lppd) { HWND hWndLV = GetDlgItem(hDlg, IDLV_MAPPER); ULONG nIndex; CHANGE_MAPPING_INFO cmi; LV_ITEM lvi; ULONG ulPropTagOld, i; LPPROP_NAME lpMappingTable; ULONG ulcMapping;
if ((nIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED)) == 0xFFFFFFFF) { nIndex = 0; ListView_SetItemState(hWndLV, nIndex, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); }
lpMappingTable = *(lppd->lppImportMapping);
cmi.lpMapping = &(lpMappingTable[nIndex]); cmi.rgPropNames = lppd->rgPropNames; cmi.ulcPropNames = NUM_EXPORT_PROPS; cmi.ulColumn = nIndex;
ulPropTagOld = cmi.lpMapping->ulPropTag;
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CSV_CHANGE_MAPPING), hDlg, ChangeMappingDialogProc, (LPARAM)&cmi);
// Fix the entry in the listbox
ZeroMemory(&lvi, sizeof(LV_ITEM));
// If there is no mapping, ensure that the field is unchosen
if (cmi.lpMapping->ulPropTag == PR_NULL || cmi.lpMapping->ulPropTag == 0 ) { cmi.lpMapping->fChosen = FALSE; }
lvi.iItem = nIndex; lvi.lParam = (LPARAM)NULL;
lvi.mask = LVIF_STATE; lvi.iSubItem = 0; // Checkbox is in first column
lvi.state = cmi.lpMapping->fChosen ? INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1) : INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1); lvi.stateMask = LVIS_STATEIMAGEMASK; if (ListView_SetItem(hWndLV, &lvi) == -1) { DebugTrace("ListView_SetItem -> %u\n", GetLastError()); Assert(FALSE); }
lvi.mask = LVIF_TEXT; lvi.iSubItem = 1; // WAB Field
lvi.pszText = cmi.lpMapping->lpszName ? cmi.lpMapping->lpszName : (LPTSTR)szEmpty; // new wab field text
if (ListView_SetItem(hWndLV, &lvi) == -1) { DebugTrace("ListView_SetItem -> %u\n", GetLastError()); Assert(FALSE); }
// if we changed the mapping, make sure there's not a duplicate proptag mapped.
if (ulPropTagOld != cmi.lpMapping->ulPropTag) { ulcMapping = *(lppd->lpcFields);
for (i = 0; i < ulcMapping; i++) { if ((i != nIndex) && cmi.lpMapping->ulPropTag == lpMappingTable[i].ulPropTag) { // Found a duplicate, nuke it.
lpMappingTable[i].ulPropTag = PR_NULL; lpMappingTable[i].lpszName = (LPTSTR)szEmpty; lpMappingTable[i].ids = 0; lpMappingTable[i].fChosen = FALSE;
// Now, redraw that row in the listview
lvi.iItem = i; lvi.lParam = (LPARAM)NULL;
// uncheck the box first
lvi.mask = LVIF_STATE; lvi.iSubItem = 0; // Checkbox is in first column
lvi.state = INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1); lvi.stateMask = LVIS_STATEIMAGEMASK; if (ListView_SetItem(hWndLV, &lvi) == -1) { DebugTrace("ListView_SetItem -> %u\n", GetLastError()); Assert(FALSE); }
// Now, change the name mapping
lvi.mask = LVIF_TEXT; lvi.iSubItem = 1; // WAB Field
lvi.pszText = (LPTSTR)szEmpty; // new wab field text
if (ListView_SetItem(hWndLV, &lvi) == -1) { DebugTrace("ListView_SetItem -> %u\n", GetLastError()); Assert(FALSE); } } } } }
/***************************************************************************
Name : FieldOrColumnName
Purpose : If the field name is empty, generate one for it.
Parameters: lpField -> Field name pointer (may be null) index = index of this column szBuffer = buffer in which to create new string if needed cbBuffer = size of szBuffer
Returns : pointer to correct field name
Comment :
***************************************************************************/ LPTSTR FieldOrColumnName(LPTSTR lpField, ULONG index, LPTSTR szBuffer, ULONG cbBuffer) { LPTSTR lpReturn = (LPTSTR)szEmpty;
if (lpField && *lpField) { return(lpField); } else { TCHAR szFormat[MAX_RESOURCE_STRING + 1]; TCHAR szNumber[11]; LPTSTR lpszArg[1] = {szNumber};
// Format a "Column 23" type of label
wnsprintf(szNumber, ARRAYSIZE(szNumber), "%u", index);
if (LoadString(hInst, IDS_CSV_COLUMN, szFormat, sizeof(szFormat))) {
if (! FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, szFormat, 0, 0, //ignored
szBuffer, cbBuffer, (va_list *)lpszArg)) { DebugTrace("FormatMessage -> %u\n", GetLastError()); } else { lpReturn = szBuffer; } } } return(lpReturn); }
/***************************************************************************
Name : ImportMapFieldsPageProc
Purpose : Process messages for "Mapi Fields" page
Parameters: standard window proc parameters
Returns : standard window proc return
Messages : WM_INITDIALOG - intializes the page WM_NOTIFY - processes the notifications sent to the page
Comment :
***************************************************************************/ INT_PTR CALLBACK ImportMapFieldsPageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND hWndLV; HIMAGELIST himl; LV_ITEM lvi; LV_COLUMN lvm; LV_HITTESTINFO lvh; POINT point; ULONG i, nIndex, nOldIndex; NMHDR * pnmhdr; RECT rect; TCHAR szBuffer[MAX_RESOURCE_STRING + 1 + 10]; ULONG cxTextWidth; static LPPROPSHEET_DATA lppd = NULL; LPPROPSHEETPAGE lppsp; HRESULT hResult; CHANGE_MAPPING_INFO cmi; LPPROP_NAME lpImportMapping;
switch (message) { case WM_INITDIALOG: lppsp = (LPPROPSHEETPAGE)lParam; lppd = (LPPROPSHEET_DATA)lppsp->lParam;
// Ensure that the common control DLL is loaded.
InitCommonControls();
// List view hwnd
hWndLV = GetDlgItem(hDlg, IDLV_MAPPER);
// How big should the text columns be?
GetClientRect(hWndLV, &rect); cxTextWidth = (rect.right - CHECK_BITMAP_WIDTH) / 2; cxTextWidth -= cxTextWidth % 2;
// Insert a column for the CSV Field Names
ZeroMemory(&lvm, sizeof(LV_COLUMN)); lvm.mask = LVCF_TEXT | LVCF_WIDTH; lvm.cx = cxTextWidth + 9; // a touch more room for the bitmap
// Get the string for the header
if (LoadString(hInst, IDS_CSV_IMPORT_HEADER_CSV, szBuffer, sizeof(szBuffer))) { lvm.pszText = szBuffer; } else { DebugTrace("Cannot load resource string %u\n", IDS_CSV_IMPORT_HEADER_CSV); lvm.pszText = NULL; Assert(FALSE); }
ListView_InsertColumn(hWndLV, 0, &lvm);
// Insert a column for the WAB Field Names
lvm.mask = LVCF_TEXT | LVCF_WIDTH; lvm.cx = cxTextWidth - 4; // room for second column text
// Get the string for the header
if (LoadString(hInst, IDS_CSV_IMPORT_HEADER_WAB, szBuffer, sizeof(szBuffer))) { lvm.pszText = szBuffer; } else { DebugTrace("Cannot load resource string %u\n", IDS_CSV_IMPORT_HEADER_WAB); lvm.pszText = NULL; Assert(FALSE); }
ListView_InsertColumn(hWndLV, 1, &lvm);
// Full row selection on listview
ListView_SetExtendedListViewStyle(hWndLV, LVS_EX_FULLROWSELECT);
// Load Image List for list view
if (himl = ImageList_LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CHECKS), CHECK_BITMAP_WIDTH, 0, RGB(128, 0, 128))) { ListView_SetImageList(hWndLV, himl, LVSIL_STATE); }
// Fill the listview
ZeroMemory(&lvi, sizeof(LV_ITEM));
// Open the file and parse out the headers line
if ((! (hResult = BuildCSVTable(szCSVFileName, lppd->rgPropNames, lppd->szSep, lppd->lppImportMapping, lppd->lpcFields, lppd->lphFile))) && ((*lppd->lpcFields) > 0)) { for (i = 0; i < *lppd->lpcFields; i++) { ULONG index; TCHAR szBuffer[MAX_RESOURCE_STRING + 1 + 10];
lpImportMapping = *lppd->lppImportMapping;
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; lvi.iItem = i; lvi.iSubItem = 0; lvi.pszText = FieldOrColumnName(lpImportMapping[i].lpszCSVName, i, szBuffer, sizeof(szBuffer)); lvi.cchTextMax = lstrlen(lvi.pszText); lvi.lParam = (LPARAM)&lpImportMapping[i]; lvi.state = lpImportMapping[i].fChosen ? INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1) : INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1); lvi.stateMask = LVIS_STATEIMAGEMASK;
if (index = ListView_InsertItem(hWndLV, &lvi) == -1) { DebugTrace("ListView_InsertItem -> %u\n", GetLastError()); Assert(FALSE); }
lvi.mask = LVIF_TEXT; // lvi.iItem = index;
lvi.iSubItem = 1; // WAB Field
lvi.pszText = lpImportMapping[i].lpszName ? lpImportMapping[i].lpszName : (LPTSTR)szEmpty; // new wab field text
lvi.lParam = (LPARAM)NULL;
if (ListView_SetItem(hWndLV, &lvi) == -1) { DebugTrace("ListView_SetItem -> %u\n", GetLastError()); Assert(FALSE); } } } else EnableWindow(GetDlgItem(hDlg,IDC_CHANGE_MAPPING),FALSE);
// Select the first item in the list
ListView_SetItemState( hWndLV, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); return(1);
case WM_NOTIFY: pnmhdr = (LPNMHDR)lParam;
switch (((NMHDR FAR *)lParam)->code) { case NM_CLICK: hWndLV = GetDlgItem(hDlg, IDLV_MAPPER);
i = GetMessagePos(); point.x = LOWORD(i); point.y = HIWORD(i); ScreenToClient(hWndLV, &point); lvh.pt = point; nIndex = ListView_HitTest(hWndLV, &lvh); // if single click on icon or double click anywhere, toggle the checkmark.
if (((NMHDR FAR *)lParam)->code == NM_DBLCLK || ( (lvh.flags & LVHT_ONITEMSTATEICON) && !(lvh.flags & LVHT_ONITEMLABEL))) { HandleCheckMark(hWndLV, nIndex, *lppd->lppImportMapping);
// if the box is now clicked, but there is no mapping, bring up the
// mapping dialog
if ((*(lppd->lppImportMapping))[nIndex].fChosen && (! (*(lppd->lppImportMapping))[nIndex].lpszName || lstrlen((*(lppd->lppImportMapping))[nIndex].lpszName) == 0)) { // Select the row
ListView_SetItemState(hWndLV, nIndex, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); HandleChangeMapping(hDlg, lppd); } } break;
case NM_DBLCLK: hWndLV = GetDlgItem(hDlg, IDLV_MAPPER); i = GetMessagePos(); point.x = LOWORD(i); point.y = HIWORD(i); ScreenToClient(hWndLV, &point); lvh.pt = point; nIndex = ListView_HitTest(hWndLV, &lvh); ListView_SetItemState(hWndLV, nIndex, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); HandleChangeMapping(hDlg, lppd); break;
case LVN_KEYDOWN: hWndLV = GetDlgItem(hDlg, IDLV_MAPPER);
// toggle checkmark if SPACE key is pressed
if (pnmhdr->hwndFrom == hWndLV) { LV_KEYDOWN *pnkd = (LV_KEYDOWN *)lParam; if (pnkd->wVKey == VK_SPACE) { nIndex = ListView_GetNextItem(hWndLV, -1, LVNI_SELECTED | LVNI_ALL); //if (nIndex >= 0)
{ HandleCheckMark(hWndLV, nIndex, *lppd->lppImportMapping);
// if the box is now clicked, but there is no mapping, bring up the
// mapping dialog
if ((*(lppd->lppImportMapping))[nIndex].fChosen && (! (*(lppd->lppImportMapping))[nIndex].lpszName || lstrlen((*(lppd->lppImportMapping))[nIndex].lpszName) == 0)) { // Select the row
ListView_SetItemState(hWndLV, nIndex, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); HandleChangeMapping(hDlg, lppd); } } } } break;
case PSN_KILLACTIVE: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); return(1); break;
case PSN_RESET: // rest to the original values
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); break;
case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH); break;
case PSN_WIZBACK: break;
case PSN_WIZFINISH: // Validate the properties selected to make sure we have
// name fields of some kind.
lpImportMapping = *lppd->lppImportMapping;
for (i = 0; i < *lppd->lpcFields; i++) { ULONG ulPropTag = lpImportMapping[i].ulPropTag; if (lpImportMapping[i].fChosen && ( ulPropTag == PR_DISPLAY_NAME || ulPropTag == PR_SURNAME || ulPropTag == PR_GIVEN_NAME || ulPropTag == PR_NICKNAME || ulPropTag == PR_COMPANY_NAME || ulPropTag == PR_EMAIL_ADDRESS || ulPropTag == PR_MIDDLE_NAME)) { return(TRUE); // OK to go do the import
} }
ShowMessageBoxParam(hDlg, IDE_CSV_NO_COLUMNS, 0); SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1); break;
default: return(FALSE); } break;
case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_CHANGE_MAPPING: HandleChangeMapping(hDlg, lppd); break; } break;
default: return(FALSE); } return(TRUE); }
INT_PTR CALLBACK ChangeMappingDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { LPCHANGE_MAPPING_INFO lpcmi = (LPCHANGE_MAPPING_INFO)GetWindowLongPtr(hwnd, DWLP_USER); static BOOL fChosenSave = FALSE; ULONG iItem;
switch (message) { case WM_INITDIALOG: { TCHAR szFormat[MAX_RESOURCE_STRING + 1]; TCHAR szBuffer[MAX_RESOURCE_STRING + 1 + 10]; LPTSTR lpszMessage = NULL; ULONG ids, i, iDefault = 0xFFFFFFFF; HWND hwndComboBox = GetDlgItem(hwnd, IDC_CSV_MAPPING_COMBO);
SetWindowLongPtr(hwnd, DWLP_USER, lParam); //Save this for future reference
lpcmi = (LPCHANGE_MAPPING_INFO)lParam;
fChosenSave = lpcmi->lpMapping->fChosen;
if (LoadString(hInst, IDS_CSV_CHANGE_MAPPING_TEXT_FIELD, szFormat, sizeof(szFormat))) { LPTSTR lpszArg[1] = {FieldOrColumnName(lpcmi->lpMapping->lpszCSVName, lpcmi->ulColumn, szBuffer, sizeof(szBuffer))};
if (! FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_ALLOCATE_BUFFER, szFormat, 0, 0, //ignored
(LPTSTR)&lpszMessage, 0, (va_list *)lpszArg)) { DebugTrace("FormatMessage -> %u\n", GetLastError()); } else { if (! SetDlgItemText(hwnd, IDC_CSV_CHANGE_MAPPING_TEXT_FIELD, lpszMessage)) { DebugTrace("SetDlgItemText -> %u\n", GetLastError()); } LocalFree(lpszMessage); } }
// Fill in the combo box
for (i = 0; i < lpcmi->ulcPropNames; i++) { SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)lpcmi->rgPropNames[i].lpszName); if (lpcmi->lpMapping->ids == lpcmi->rgPropNames[i].ids) { SendMessage(hwndComboBox, CB_SETCURSEL, (WPARAM)i, 0); } }
// Add blank line
SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)szEmpty); if (lpcmi->lpMapping->ids == 0) { SendMessage(hwndComboBox, CB_SETCURSEL, (WPARAM)(i + 1), 0); }
// Init the checkbox
CheckDlgButton(hwnd, IDC_CSV_MAPPING_SELECT, fChosenSave ? BST_CHECKED : BST_UNCHECKED); return(TRUE); }
case WM_COMMAND : switch (LOWORD(wParam)) { case IDCANCEL: lpcmi->lpMapping->fChosen = fChosenSave; SendMessage(hwnd, WM_CLOSE, 0, 0L); return(0);
case IDCLOSE: SendMessage(hwnd, WM_CLOSE, 0, 0L); return(0);
case IDOK: // Set the state of the parameter
// Get the mapping
if ((iItem = (ULONG) SendMessage(GetDlgItem(hwnd, IDC_CSV_MAPPING_COMBO), CB_GETCURSEL, 0, 0)) != CB_ERR) { if (iItem >= lpcmi->ulcPropNames) { lpcmi->lpMapping->lpszName = (LPTSTR)szEmpty; lpcmi->lpMapping->ids = 0; lpcmi->lpMapping->ulPropTag = PR_NULL; lpcmi->lpMapping->fChosen = FALSE; } else { lpcmi->lpMapping->lpszName = rgPropNames[iItem].lpszName; lpcmi->lpMapping->ids = rgPropNames[iItem].ids; lpcmi->lpMapping->ulPropTag = rgPropNames[iItem].ulPropTag; } } SendMessage(hwnd, WM_CLOSE, 0, 0); return(0);
case IDM_EXIT: SendMessage(hwnd, WM_DESTROY, 0, 0L); return(0);
case IDC_CSV_MAPPING_SELECT: switch (HIWORD(wParam)) { case BN_CLICKED: if ((int)LOWORD(wParam) == IDC_CSV_MAPPING_SELECT) { // toggle the checkbox
lpcmi->lpMapping->fChosen = ! lpcmi->lpMapping->fChosen; CheckDlgButton(hwnd, IDC_CSV_MAPPING_SELECT, lpcmi->lpMapping->fChosen ? BST_CHECKED : BST_UNCHECKED); } break; } break; } break;
case IDCANCEL: SendMessage(hwnd, WM_CLOSE, 0, 0); break;
case WM_CLOSE: EndDialog(hwnd, FALSE); return(0);
default: return(FALSE); }
return(TRUE); }
|