STEP1.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:34k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // Microsoft OLE DB TABLECOPY Sample
  3. // Copyright (C) 1995-1998 Microsoft Corporation
  4. //
  5. // @doc
  6. //
  7. // @module STEP1.CPP
  8. //
  9. //-----------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////
  11. // Includes
  12. //
  13. /////////////////////////////////////////////////////////////////////
  14. #include "wizard.h"
  15. #include "common.h"
  16. #include "table.h"
  17. /////////////////////////////////////////////////////////////////////
  18. // Defines
  19. //
  20. /////////////////////////////////////////////////////////////////////
  21. //Enum Column Header for the ListView controls
  22. enum COL_HEADERS
  23. {
  24. //IDL_COLUMNS
  25. COL_COLNAME = 0, //ColInfo.pwszName
  26. COL_COLTYPE = 1, //ColInfo.wType
  27. COL_COLORDINAL = 2, //ColInfo.iOrdinal
  28. COL_COLSIZE = 3, //ColInfo.ulColumnSize
  29. COL_COLPREC = 4, //ColInfo.bPrecision
  30. COL_COLSCALE = 5, //ColInfo.bScale
  31. COL_COLISFIXED = 6, //ColInfo.dwFlags ISFIXEDLENGTH
  32. COL_COLISLONG = 7, //ColInfo.dwFlags ISLONG
  33. COL_COLISNULLABLE = 8, //ColInfo.dwFlags ISNULLABLE
  34. COL_COLWRITE = 9, //ColInfo.dwFlags WRITE
  35. COL_COLISROWID =10, //ColInfo.dwFlags ISROWID
  36. COL_COLISROWVER =11, //ColInfo.dwFlags ISROWVER
  37. };
  38. enum EICON
  39. {
  40. ICON_CATALOG = 0,
  41. ICON_SCHEMA = 1,
  42. ICON_TYPE = 2,
  43. ICON_TABLE = 3,
  44. ICON_SYSTABLE = 4,
  45. ICON_VIEW = 5,
  46. ICON_SYNONYM = 6,
  47. ICON_COLUMN = 0,
  48. ICON_READONLY = 1,
  49. ICON_LONG = 2,
  50. };
  51. /////////////////////////////////////////////////////////////////////
  52. // CS1Dialog::CS1Dialog
  53. //
  54. /////////////////////////////////////////////////////////////////////
  55. CS1Dialog::CS1Dialog(HWND hWnd, HINSTANCE hInst, CTableCopy* pCTableCopy)
  56. : CDialogBase(hWnd, hInst)
  57. {
  58. ASSERT(pCTableCopy);
  59. m_pCTableCopy = pCTableCopy;
  60. m_fEditing = FALSE;
  61. m_cTables = 0;
  62. m_rgTableInfo = NULL;
  63. }
  64. /////////////////////////////////////////////////////////////////////
  65. // CS1Dialog::~CS1Dialog
  66. //
  67. /////////////////////////////////////////////////////////////////////
  68. CS1Dialog::~CS1Dialog()
  69. {
  70. SAFE_FREE(m_rgTableInfo);
  71. }
  72. /////////////////////////////////////////////////////////////////////////////
  73. // ULONG CS1Dialog::Display
  74. //
  75. /////////////////////////////////////////////////////////////////////////////
  76. ULONG CS1Dialog::Display()
  77. {
  78. //Create a Modal dialog box
  79. return DialogBoxParam(m_hInst, MAKEINTRESOURCE(IDD_FROM_INFO), NULL, DlgProc, (LPARAM)this);
  80. }
  81. /////////////////////////////////////////////////////////////////////
  82. // CS1Dialog::DlgProc
  83. //
  84. /////////////////////////////////////////////////////////////////////
  85. BOOL WINAPI CS1Dialog::DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  86. {
  87. switch(msg) 
  88. {
  89. case WM_INITDIALOG:
  90. {
  91. Busy();
  92. CS1Dialog* pThis = (CS1Dialog*)lParam;
  93. SetWindowLong(hWnd, GWL_USERDATA, (LONG)pThis);
  94. //On INIT we know we have a valid hWnd to store
  95. CenterDialog(hWnd);
  96. pThis->m_hWnd = hWnd;
  97. CTable* pCFromTable = pThis->m_pCTableCopy->m_pCFromTable;
  98. //Init all controls to the default values
  99. pThis->InitControls();
  100. // If there is a source to look at, Display the table list
  101. if(pCFromTable->IsConnected()) 
  102. pThis->ResetTableList(GetDlgItem(hWnd, IDL_TABLES), GetDlgItem(hWnd, IDL_COLUMNS));
  103. pThis->RefreshControls();
  104. pThis->m_pCTableCopy->m_pCWizard->DestroyPrevStep(WIZ_STEP1);
  105. return HANDLED_MSG;
  106. }//case WM_INITDIALOG
  107. case WM_COMMAND:
  108. {
  109. //Obtain the "this" pointer
  110. CS1Dialog* pThis = (CS1Dialog*)GetWindowLong(hWnd, GWL_USERDATA);
  111. CTable* pCFromTable = pThis->m_pCTableCopy->m_pCFromTable;
  112. CTable* pCToTable = pThis->m_pCTableCopy->m_pCToTable;
  113. CDataSource* pCToDataSource = pCToTable->m_pCDataSource;
  114. CDataSource* pCFromDataSource = pCFromTable->m_pCDataSource;
  115. //Filter out any Control Notification codes
  116. if(GET_WM_COMMAND_CMD(wParam, lParam) > 1)
  117. {
  118. return UNHANDLED_MSG;
  119. }
  120. //LBN_SELCHANGE ListBox Selection change
  121. if(GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE
  122. && IDC_PROVIDER_NAME == GET_WM_COMMAND_ID(wParam, lParam)) 
  123. {
  124. Busy();
  125. //Get new selection
  126. LONG iSel = 0;
  127. if((iSel = SendMessage(GetDlgItem(pThis->m_hWnd, IDC_PROVIDER_NAME), CB_GETCURSEL, 0, 0L)) != CB_ERR)
  128. {
  129. //Since we have the CBS_SORT turned on, the order in the Combo Box does
  130. //not match our array, so we pass the array index (lParam) as the item data
  131. LONG lParam = SendMessage(GetDlgItem(pThis->m_hWnd, IDC_PROVIDER_NAME), CB_GETITEMDATA, iSel, 0L);
  132. if((lParam < (LONG)pCFromDataSource->m_cProviderInfo) && (wcscmp(pCFromDataSource->m_rgProviderInfo[lParam].wszName, pCFromDataSource->m_pwszProviderName)!=0))
  133. {
  134. //Clear Table/Column List Views
  135. SendMessage(GetDlgItem(hWnd, IDL_TABLES), TVM_DELETEITEM, (WPARAM)0, (LPARAM)TVI_ROOT);
  136. SendMessage(GetDlgItem(hWnd, IDL_COLUMNS), LVM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0);
  137. //Clear Table info
  138. memset(&pCFromTable->m_TableInfo, 0, sizeof(TABLEINFO));
  139. pCFromTable->m_wszQualTableName[0] = EOL;
  140. //Disconnect from the DataSource and Update controls
  141. pCFromTable->m_pCDataSource->Disconnect();
  142. pThis->RefreshControls();
  143. }
  144. }
  145. return HANDLED_MSG;
  146. }
  147. if(pThis->m_fEditing)
  148. {
  149. //There is a bug in the TreeView control for editing here is KB article
  150. //Article ID: Q130691 BUG: ESC/ENTER Keys Don't Work When Editing Labels in TreeView
  151. //So one way to work around this is to just have a flag (m_fEditing)
  152. //to indicate we were in editing mode.
  153. SendDlgItemMessage(hWnd, IDL_TABLES, TVM_ENDEDITLABELNOW, (WPARAM) (wParam==IDCANCEL ? TRUE : FALSE), (LPARAM)0);
  154. return HANDLED_MSG;
  155. }
  156. // Now check for regular command ids
  157. switch(GET_WM_COMMAND_ID(wParam, lParam)) 
  158. {
  159. case IDB_FROM_CONNECT:
  160. {
  161. //Try to connect to the DataSource
  162. Busy();
  163. if(pCFromTable->Connect(hWnd))
  164. {
  165. Busy();
  166. //Clear Table info
  167. memset(&pCFromTable->m_TableInfo, 0, sizeof(TABLEINFO));
  168. pCFromTable->m_wszQualTableName[0] = EOL;
  169. //ResetTableList
  170. pThis->ResetTableList(GetDlgItem(hWnd, IDL_TABLES), GetDlgItem(hWnd, IDL_COLUMNS));
  171. }
  172. pThis->RefreshControls();
  173. return HANDLED_MSG;
  174. }//case IDB_FROM_CONNECT
  175.                 case IDOK:
  176. Busy();
  177. pThis->GetTableColInfo(GetDlgItem(hWnd, IDL_COLUMNS));
  178. pThis->m_pCTableCopy->m_pCWizard->DisplayStep(WIZ_STEP2);
  179. return HANDLED_MSG;
  180. case IDCANCEL:
  181. Busy();
  182. EndDialog(hWnd, GET_WM_COMMAND_ID(wParam, lParam));
  183. return HANDLED_MSG;
  184. }//switch GET_WM_COMMAND_ID
  185. return UNHANDLED_MSG;
  186. }//case WM_COMMAND
  187. // Now look for WM_NOTIFY messages
  188. case WM_NOTIFY:
  189. {
  190. if(wParam == IDL_COLUMNS)
  191. {
  192. //Obtain the "this" pointer
  193. CS1Dialog* pThis = (CS1Dialog*)GetWindowLong(hWnd, GWL_USERDATA);
  194. NM_LISTVIEW* pListView = (NM_LISTVIEW*)lParam;
  195. switch(pListView->hdr.code)
  196. {
  197. case LVN_ITEMCHANGED:
  198. {
  199. //Refresh Controls, ("Next" button)
  200. pThis->RefreshControls();
  201. return UNHANDLED_MSG;
  202. }
  203. }
  204. return UNHANDLED_MSG;
  205. }
  206. if(wParam == IDL_TABLES)
  207. {
  208. //Obtain the "this" pointer
  209. CS1Dialog* pThis = (CS1Dialog*)GetWindowLong(hWnd, GWL_USERDATA);
  210. CTable* pCFromTable = pThis->m_pCTableCopy->m_pCFromTable;
  211. NM_TREEVIEW* pTreeView = (NM_TREEVIEW*)lParam;
  212. switch(pTreeView->hdr.code)
  213. {  
  214. case TVN_BEGINLABELEDIT:
  215. {
  216. //Idicate we have started to edit
  217. pThis->m_fEditing = TRUE;
  218. return FALSE; //Allow the edited change
  219. }
  220. case TVN_ENDLABELEDIT:
  221. {
  222. Busy();
  223. pThis->m_fEditing = FALSE;
  224. TV_DISPINFO* pDispInfo = (TV_DISPINFO*)lParam;
  225. //If Schemas are available - don't allow the change
  226. if(pCFromTable->m_pCDataSource->m_pIDBSchemaRowset)
  227. return FALSE;
  228. //Just need to obtain the new tablename...
  229. if(pDispInfo->item.pszText)
  230. {
  231. //Now update the window TableName myself
  232. TV_ITEM tvItem = { TVIF_TEXT | TVIF_STATE, pDispInfo->item.hItem, TVIS_SELECTED, TVIS_SELECTED, pDispInfo->item.pszText, 0, 0, 0, 0, 0};
  233. SendDlgItemMessage(hWnd, IDL_TABLES, TVM_SETITEM, (WPARAM)0, (LPARAM)&tvItem);
  234. //Change the TableName (if different)
  235. memset(&pThis->m_rgTableInfo[0], 0, sizeof(TABLEINFO));
  236. ConvertToWCHAR(pDispInfo->item.pszText, pThis->m_rgTableInfo[0].wszTableName, MAX_NAME_LEN);
  237. pThis->ChangeTableName(0); 
  238. }
  239. //Refresh Controls ("Next" button);
  240. pThis->RefreshControls();
  241. return TRUE; //Allow the edited change
  242. }
  243. case TVN_SELCHANGED:
  244. {
  245. //There is a problem with the SELCHANGED notification
  246. //It can be sent when either a item is selected or
  247. //DELETED, since when an item deleted the selection moves
  248. //to a different selection.
  249. if((pTreeView->itemNew.state == TVIS_SELECTED && pTreeView->action)
  250. || (pTreeView->itemNew.state & TVIS_SELECTED && pTreeView->itemNew.state != TVIS_SELECTED)) 
  251. {
  252. Busy();
  253. //We assume it sends us the Param of the item
  254. ASSERT(pTreeView->itemNew.mask & TVIF_PARAM);
  255. //Change the TableName (if different)
  256. pThis->ChangeTableName(pTreeView->itemNew.lParam); 
  257. }
  258. //Refresh Controls ("Next" button);
  259. pThis->RefreshControls();
  260. return UNHANDLED_MSG;
  261. }
  262. }
  263. return UNHANDLED_MSG;
  264. }//IDL_TABLES
  265. return UNHANDLED_MSG;
  266. }//WM_NOTIFY
  267. }//msg
  268. return UNHANDLED_MSG;
  269. }
  270. /////////////////////////////////////////////////////////////////////////////
  271. // BOOL CS1Dialog::InitControls
  272. //
  273. /////////////////////////////////////////////////////////////////////////////
  274. BOOL CS1Dialog::InitControls()
  275. {
  276. HWND hWndTable = GetDlgItem(m_hWnd, IDL_TABLES);
  277. HWND hWndCol = GetDlgItem(m_hWnd, IDL_COLUMNS);
  278. HWND hWndProv = GetDlgItem(m_hWnd, IDC_PROVIDER_NAME);
  279. CDataSource* pCDataSource = m_pCTableCopy->m_pCFromTable->m_pCDataSource;
  280. //Create the Table ImageList
  281. HIMAGELIST hTableImageList = ImageList_Create(16, 16, ILC_MASK, 1, 0 );
  282. //IDI_CATALOG - normal catalog icon
  283. HICON hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_CATALOG));
  284. ImageList_AddIcon(hTableImageList, hIcon);
  285. //IDI_SCHEMA - normal schema icon
  286. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_SCHEMA));
  287. ImageList_AddIcon(hTableImageList, hIcon);
  288. //IDI_TYPE - normal type icon
  289. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_TYPE));
  290. ImageList_AddIcon(hTableImageList, hIcon);
  291. //IDI_TABLE - normal table icon
  292. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_TABLE));
  293. ImageList_AddIcon(hTableImageList, hIcon);
  294. //IDI_SYSTABLE - normal system table icon
  295. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_SYSTABLE));
  296. ImageList_AddIcon(hTableImageList, hIcon);
  297. //IDI_VIEW - normal view icon
  298. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_VIEW));
  299. ImageList_AddIcon(hTableImageList, hIcon);
  300. //IDI_SYNONYM - normal synonym icon
  301. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_SYNONYM));
  302. ImageList_AddIcon(hTableImageList, hIcon);
  303. //Set image list to the Table Window 
  304. TreeView_SetImageList(hWndTable, hTableImageList, TVSIL_NORMAL);
  305. //Create the Col ImageList
  306. HIMAGELIST hColImageList = ImageList_Create(16, 16, ILC_MASK, 1, 0 );
  307. //IDI_COLUMN - normal column icon
  308. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_COLUMN));
  309. ImageList_AddIcon(hColImageList, hIcon);
  310. //IDI_COLUMNREAD - read-only column icon
  311. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_COLUMNREAD));
  312. ImageList_AddIcon(hColImageList, hIcon);
  313. //IDI_COLUMNLONG - long column icon
  314. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_COLUMNLONG));
  315. ImageList_AddIcon(hColImageList, hIcon);
  316. //Set image list to the Table Window 
  317. ListView_SetImageList(hWndCol, hColImageList, LVSIL_SMALL);
  318. //ListView COLUMNS
  319. LV_InsertColumn(hWndCol, COL_COLNAME, "ColName");
  320. LV_InsertColumn(hWndCol, COL_COLTYPE, "Type");
  321. LV_InsertColumn(hWndCol, COL_COLSIZE, "Size");
  322. LV_InsertColumn(hWndCol, COL_COLORDINAL, "Ordinal");
  323. LV_InsertColumn(hWndCol, COL_COLPREC, "Precision");
  324. LV_InsertColumn(hWndCol, COL_COLSCALE, "Scale");
  325. LV_InsertColumn(hWndCol, COL_COLISFIXED, "ISFIXED");
  326. LV_InsertColumn(hWndCol, COL_COLISLONG, "ISLONG");
  327. LV_InsertColumn(hWndCol, COL_COLISNULLABLE, "ISNULLABLE");
  328. LV_InsertColumn(hWndCol, COL_COLWRITE, "WRITE");
  329. LV_InsertColumn(hWndCol, COL_COLISROWID, "ISROWID");
  330. LV_InsertColumn(hWndCol, COL_COLISROWVER, "ISROWVER");
  331. //AutoSize all columns
  332. for(ULONG i=0; i<=COL_COLISROWVER; i++)
  333. SendMessage(hWndCol, LVM_SETCOLUMNWIDTH, (WPARAM)i, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
  334. //Use Extended ListView Styles!
  335. SendMessage(hWndCol, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES);
  336. //Initialize the Provider List (if not done so already)
  337. if(pCDataSource->m_rgProviderInfo == NULL)
  338. pCDataSource->GetProviders();
  339. WCHAR wszBuffer[MAX_NAME_LEN*2];
  340. //Fill out the provider name combo box.
  341. for(i=0; i<pCDataSource->m_cProviderInfo; i++)
  342. {
  343. //Add the name to the list
  344. //Since we have the CBS_SORT turned on, the order in the Combo Box does
  345. //not match our array, so we pass the array index (lParam) as the item data
  346. swprintf(wszBuffer, wsz_PROVIDER_INFO_, pCDataSource->m_rgProviderInfo[i].wszName, pCDataSource->m_rgProviderInfo[i].wszDescription);
  347. LONG iIndex = wSendMessage(hWndProv, CB_ADDSTRING, (WPARAM)0, wszBuffer);
  348. SendMessage(hWndProv, CB_SETITEMDATA, (WPARAM)iIndex, (LPARAM)i);
  349. }
  350. //By default, it selects MSDASQL
  351. if(pCDataSource->m_pwszProviderName == NULL)
  352. pCDataSource->m_pwszProviderName = L"MSDASQL";
  353. //Try and select the previous selected Provider
  354. if(CB_ERR == wSendMessage(hWndProv, CB_SELECTSTRING, 0, pCDataSource->m_pwszProviderName))
  355. {
  356. //If not found, just select the first one
  357. SendMessage(hWndProv, CB_SETCURSEL, 0, 0);
  358. }
  359. //Indicate were not in the middle of an TreeView editing command
  360. m_fEditing = FALSE;
  361. // Enable Connect button only if there are providers installed.
  362. EnableWindow(GetDlgItem(m_hWnd, IDB_FROM_CONNECT), SendMessage(hWndProv, CB_GETCURSEL, 0, 0L) != CB_ERR);
  363. return TRUE;
  364. }
  365. /////////////////////////////////////////////////////////////////////////////
  366. // BOOL CS1Dialog::RefreshControls
  367. //
  368. /////////////////////////////////////////////////////////////////////////////
  369. BOOL CS1Dialog::RefreshControls()
  370. {
  371. CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
  372. CDataSource* pCDataSource = pCFromTable->m_pCDataSource;
  373. // Must have a connection to edit other controls
  374. BOOL fConnected = pCFromTable->IsConnected();
  375. ULONG cSelColumns = SendDlgItemMessage(m_hWnd, IDL_COLUMNS, LVM_GETSELECTEDCOUNT, 0, 0);
  376. //Enable dialog items, only if connected
  377. EnableWindow(GetDlgItem(m_hWnd, IDL_TABLES), fConnected);
  378. EnableWindow(GetDlgItem(m_hWnd, IDL_COLUMNS), fConnected);
  379. EnableWindow(GetDlgItem(m_hWnd, IDT_FROMTABLEHELP), fConnected);
  380.  
  381. //Enable OK/Next if there is a table and at least 1 column selected
  382. EnableWindow(GetDlgItem(m_hWnd, IDOK), fConnected && cSelColumns);
  383. //Store the selected ProviderName and ProviderDesc
  384. LONG iSel = 0;
  385. if((iSel = SendMessage(GetDlgItem(m_hWnd, IDC_PROVIDER_NAME), CB_GETCURSEL, 0, 0L)) != CB_ERR)
  386. {
  387. //Since we have the CBS_SORT turned on, the order in the Combo Box does
  388. //not match our array, so we pass the array index (lParam) as the item data
  389. LONG lParam = SendMessage(GetDlgItem(m_hWnd, IDC_PROVIDER_NAME), CB_GETITEMDATA, iSel, 0L);
  390. ASSERT(lParam < (LONG)pCDataSource->m_cProviderInfo);
  391. pCDataSource->m_pwszProviderName = pCDataSource->m_rgProviderInfo[lParam].wszName;
  392. pCDataSource->m_pwszProviderParseName = pCDataSource->m_rgProviderInfo[lParam].wszParseName;
  393. }
  394. // Show user the connection string
  395. if(fConnected)
  396. {
  397. //CONNECT_STRING
  398. wSetDlgItemText(m_hWnd, IDT_CONNECT, wsz_CONNECT_STRING_, 
  399. pCDataSource->m_pwszProviderName,
  400. pCDataSource->m_pwszDataSource, 
  401. pCDataSource->m_pwszDBMS,
  402. pCDataSource->m_pwszDBMSVer,
  403. pCDataSource->m_pwszProviderFileName,
  404. pCDataSource->m_pwszProviderVer);
  405. //TABLEHELPMSG
  406. //Display the Qualified TableName
  407. if(pCFromTable->m_TableInfo.wszTableName[0])
  408. wSetDlgItemText(m_hWnd, IDT_FROMTABLEHELP, wsz_FROMQUALTABLE_, pCFromTable->m_wszQualTableName, cSelColumns);
  409. else 
  410. wSetDlgItemText(m_hWnd, IDT_FROMTABLEHELP, wsz_FROMTABLEHELP_, pCDataSource->m_pwszTableTerm);
  411. }
  412. else
  413. {
  414. //NO CONNECT_STRING
  415. wSetDlgItemText(m_hWnd, IDT_CONNECT, wsz_NOT_CONNECTED);
  416. }
  417. return TRUE;
  418. }
  419. /////////////////////////////////////////////////////////////////////////////
  420. // BOOL CS1Dialog::GetTableColInfo
  421. //
  422. /////////////////////////////////////////////////////////////////////////////
  423. BOOL CS1Dialog::GetTableColInfo(HWND hWndCol)
  424. {
  425. CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
  426. // Get the count of selected items
  427. LONG cSelColumns = SendMessage(hWndCol, LVM_GETSELECTEDCOUNT, (WPARAM)0, (LPARAM)0);
  428. LONG iIndex = -1;
  429. //Loop over all the selected columns in the list
  430. pCFromTable->m_cColumns = cSelColumns;
  431. for(LONG i=0; i<cSelColumns; i++) 
  432. {
  433. iIndex = SendMessage(hWndCol, LVM_GETNEXTITEM, (WPARAM)iIndex, (LPARAM)LVNI_SELECTED);
  434. //"compact" the m_rgColDesc array to only the selected items
  435. if(iIndex != LVM_ERR)
  436. memmove(&pCFromTable->m_rgColDesc[i], &pCFromTable->m_rgColDesc[iIndex], sizeof(COLDESC));
  437. }
  438. return TRUE;
  439. }
  440. /////////////////////////////////////////////////////////////////////////////
  441. // BOOL CS1Dialog::CreateTableNode
  442. //
  443. /////////////////////////////////////////////////////////////////////////////
  444. BOOL CS1Dialog::CreateTableNode(TREEINFO* rgTreeInfo, ULONG ulNameOffset, LONG iParam, LONG iImage, LONG iSelectedImage)
  445. {
  446. //ulNameOffset is the offset into TABELEINFO indicating
  447. //Catalog / Schema / Type name were interested in comparing
  448. ASSERT(ulNameOffset == offsetof(TABLEINFO, wszCatalogName)
  449. || ulNameOffset == offsetof(TABLEINFO, wszSchemaName)
  450. || ulNameOffset == offsetof(TABLEINFO, wszType));
  451. //Create the specified node in the tree.
  452. //Basically this is a fairly complex function that builds the nodes to the 
  453. //TreeView control, listing Catalog/Schema/TableType/TableName heieracrcy.
  454. //This is an extremly simple algortym that loops over the specified column 
  455. //(Catalog/Schema/Type) and adds only unique names as a node to the TreeView.
  456. //It then updates "rgTreeInfo" hParents and hItems accordingly.
  457. CHAR szBuffer[MAX_NAME_LEN];
  458. //Loop over all Tables
  459. ULONG cFoundInfo = 0;
  460. for(ULONG i=0; i<m_cTables; i++)
  461. {
  462. BOOL bFound = FALSE;
  463. WCHAR* pwszName = (WCHAR*)((BYTE*)&m_rgTableInfo[i] + ulNameOffset);
  464. //Try to find Type value in the FoundList
  465. for(ULONG j=0; j<cFoundInfo; j++)
  466. {
  467. ULONG ulFoundIndex = rgTreeInfo[j].ulIndex;
  468. WCHAR* pwszFoundName = (WCHAR*)((BYTE*)&m_rgTableInfo[ulFoundIndex] + ulNameOffset);
  469. if(wcscmp(pwszName, pwszFoundName)==0
  470. && rgTreeInfo[i].hParent == rgTreeInfo[ulFoundIndex].hParent)
  471. {
  472. bFound = TRUE;
  473. rgTreeInfo[i].hItem = rgTreeInfo[ulFoundIndex].hItem;
  474. break;
  475. }
  476. }
  477. if(!bFound && pwszName[0])
  478. {
  479. //Add it to the list
  480. rgTreeInfo[cFoundInfo].ulIndex = i;
  481. cFoundInfo++;
  482. //Add it to the TreeView
  483. ConvertToMBCS(pwszName, szBuffer, MAX_NAME_LEN);
  484. rgTreeInfo[i].hItem = TV_InsertItem(GetDlgItem(m_hWnd, IDL_TABLES), rgTreeInfo[i].hParent, TVI_SORT, szBuffer, iParam, iImage, iSelectedImage);
  485. }
  486. }
  487. //Update Parents
  488. for(i=0; i<m_cTables; i++)
  489. rgTreeInfo[i].hParent = rgTreeInfo[i].hItem;
  490. return TRUE;
  491. }
  492. /////////////////////////////////////////////////////////////////////////////
  493. // BOOL CS1Dialog::ResetTableList
  494. //
  495. /////////////////////////////////////////////////////////////////////////////
  496. BOOL CS1Dialog::ResetTableList(HWND hWndTable, HWND hWndCol)
  497. {
  498. HRESULT hr;
  499. CHAR szBuffer[MAX_NAME_LEN];
  500. IRowset* pIRowset = NULL;
  501. IAccessor* pIAccessor = NULL;
  502. //get the data
  503. HROW* rghRows = NULL;
  504. ULONG i,cRowsObtained = 0;
  505. BOOL    bFound = FALSE;
  506. HACCESSOR hAccessor = DB_NULL_HACCESSOR;
  507. TREEINFO* rgTreeInfo = NULL;
  508. //Use the passed in Session interface
  509. CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
  510. CDataSource* pCFromDataSource = pCFromTable->m_pCDataSource;
  511. IOpenRowset* pIOpenRowset = pCFromTable->m_pCDataSource->m_pIOpenRowset;
  512. IDBSchemaRowset* pIDBSchemaRowset = pCFromTable->m_pCDataSource->m_pIDBSchemaRowset;
  513. //Delete all previous items
  514. SendMessage(hWndTable, TVM_DELETEITEM, (WPARAM)0, (LPARAM)TVI_ROOT);
  515. SendMessage(hWndCol, LVM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0);
  516. // Bind the user and table name for the list
  517. const static ULONG cBindings = 4;
  518. const static DBBINDING rgBindings[cBindings] = 
  519. {
  520. //TABLE_CATALOG
  521. 1,  
  522. offsetof(TABLEINFO, wszCatalogName), // offset of value in consumers buffer
  523. 0, // offset of length
  524. 0, // offset of status
  525. NULL, // reserved
  526. NULL, // for ole object
  527. NULL, // reserved
  528. DBPART_VALUE, // specifies Value is bound only
  529. DBMEMOWNER_CLIENTOWNED, // memory is client owned
  530. DBPARAMIO_NOTPARAM, // 
  531. MAX_NAME_LEN, // size in bytes of the value part in the consumers buffer
  532. 0,  // reserved
  533. DBTYPE_WSTR,  // data type indicator
  534. 0, // precision
  535. 0,  // scale
  536. //TABLE_SCHEMA
  537. 2,  
  538. offsetof(TABLEINFO, wszSchemaName), // offset of value in consumers buffer
  539. 0, // offset of length
  540. 0, // offset of status
  541. NULL, // reserved
  542. NULL, // for ole object
  543. NULL, // reserved
  544. DBPART_VALUE, // specifies Value is bound only
  545. DBMEMOWNER_CLIENTOWNED, // memory is client owned
  546. DBPARAMIO_NOTPARAM, // 
  547. MAX_NAME_LEN, // size in bytes of the value part in the consumers buffer
  548. 0,  // reserved
  549. DBTYPE_WSTR,  // data type indicator
  550. 0, // precision
  551. 0,  // scale
  552. //TABLE_NAME
  553. 3,   // ordinal
  554. offsetof(TABLEINFO, wszTableName), // offset of value in consumers buffer
  555. 0, // offset of length in consumers buffer
  556. 0, // offset of status in consumers buffer
  557. NULL, // reserved
  558. NULL, // for ole object
  559. NULL, // reserved
  560. DBPART_VALUE, // specifies Value only
  561. DBMEMOWNER_CLIENTOWNED, // memory is client owned
  562. DBPARAMIO_NOTPARAM, // input param
  563. MAX_NAME_LEN, // size in bytes of the value part in the consumers buffer
  564. 0,  // reserved
  565. DBTYPE_WSTR,  // data type indicator
  566. 0, // precision
  567. 0,  // scale
  568. //TABLE_TYPE
  569. 4,   // ordinal
  570. offsetof(TABLEINFO, wszType), // offset of value in consumers buffer
  571. 0, // offset of length in consumers buffer
  572. 0, // offset of status in consumers buffer
  573. NULL, // reserved
  574. NULL, // for ole object
  575. NULL, // reserved
  576. DBPART_VALUE, // specifies Value only
  577. DBMEMOWNER_CLIENTOWNED, // memory is client owned
  578. DBPARAMIO_NOTPARAM, // input param
  579. MAX_NAME_LEN, // size in bytes of the value part in the consumers buffer
  580. 0,  // reserved
  581. DBTYPE_WSTR,  // data type indicator
  582. 0, // precision
  583. 0,  // scale
  584.     };
  585. //Reset TableInfo
  586. m_cTables = 0;
  587. SAFE_FREE(m_rgTableInfo);
  588. //Provider doesn't have to support IDBSchemaRowset
  589. if(pIDBSchemaRowset)
  590. {
  591. //GetRowset
  592. //DBSCHEMA_TABLES is required a SCHEMA (if IDBSchemaRowset is supported)
  593. XTESTC(hr = pIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_TABLES, 0, NULL, IID_IRowset, 0, NULL,(IUnknown **)&pIRowset));
  594. //Create the Accessor
  595. XTESTC(hr = pIRowset->QueryInterface(IID_IAccessor, (void **)&pIAccessor));
  596. XTESTC(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBindings, rgBindings, 0, &hAccessor, NULL));
  597. //Grab all the rows
  598. while(TRUE)
  599. {
  600. XTESTC(hr = pIRowset->GetNextRows(NULL, 0, MAX_BLOCK_SIZE, &cRowsObtained, &rghRows));
  601. //ENDOFROWSET
  602. if(cRowsObtained==0)
  603. break;
  604. //Realloc Table struct for Table
  605. SAFE_REALLOC(m_rgTableInfo, TABLEINFO, m_cTables + cRowsObtained);
  606. memset(&m_rgTableInfo[m_cTables], 0, cRowsObtained*sizeof(TABLEINFO));
  607. //Loop over the rows retrived
  608. for(i=0; i<cRowsObtained; i++) 
  609. {
  610. //Get the Data
  611. XTESTC(hr = pIRowset->GetData(rghRows[i], hAccessor, &m_rgTableInfo[m_cTables]));
  612. m_cTables++;
  613. }
  614. //Release the rows obtained
  615. XTESTC(hr = pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL));
  616. SAFE_FREE(rghRows);
  617. }
  618. }
  619. //Provider doesn't have to support IDBSchemaRowset
  620. if(pIDBSchemaRowset == NULL)
  621. {
  622. m_cTables = 1;
  623. SAFE_ALLOC(m_rgTableInfo, TABLEINFO, 1);
  624. memset(m_rgTableInfo, 0, sizeof(TABLEINFO));
  625. if(pCFromTable->m_TableInfo.wszTableName[0])
  626. {
  627. //Just Display the TableName in the EditBox
  628. wcscpy(m_rgTableInfo[0].wszTableName, pCFromTable->m_TableInfo.wszTableName);
  629. }
  630. else
  631. {
  632. //Just Display "Enter - <TableTerm>"
  633. wcscpy(m_rgTableInfo[0].wszTableName, L"Enter - ");
  634. wcscat(m_rgTableInfo[0].wszTableName, pCFromDataSource->m_pwszTableTerm);
  635. }
  636. }
  637. //Create rgTreeInfo array
  638. SAFE_ALLOC(rgTreeInfo, TREEINFO, m_cTables);
  639. memset(rgTreeInfo, 0, m_cTables*sizeof(TREEINFO));
  640. //Create Tree Nodes for the TreeView control
  641. CreateTableNode(rgTreeInfo, offsetof(TABLEINFO, wszCatalogName), -1, ICON_CATALOG, ICON_CATALOG); 
  642. CreateTableNode(rgTreeInfo, offsetof(TABLEINFO, wszSchemaName),  -1, ICON_SCHEMA, ICON_SCHEMA); 
  643. CreateTableNode(rgTreeInfo, offsetof(TABLEINFO, wszType),  -1, ICON_TYPE, ICON_TYPE); 
  644. //Now display all the tables
  645. for(i=0; i<m_cTables; i++)
  646. {
  647. //Add it to the TreeView
  648. ConvertToMBCS(m_rgTableInfo[i].wszTableName, szBuffer, MAX_NAME_LEN);
  649. if(wcscmp(m_rgTableInfo[i].wszType, L"TABLE")==0)
  650. rgTreeInfo[i].hItem = TV_InsertItem(hWndTable, rgTreeInfo[i].hParent, TVI_SORT, szBuffer, (LONG)i, ICON_TABLE, ICON_TABLE);
  651. else if(wcscmp(m_rgTableInfo[i].wszType, L"VIEW")==0)
  652. rgTreeInfo[i].hItem = TV_InsertItem(hWndTable, rgTreeInfo[i].hParent, TVI_SORT, szBuffer, (LONG)i, ICON_VIEW, ICON_VIEW);
  653. else if(wcscmp(m_rgTableInfo[i].wszType, L"SYSTEM TABLE")==0)
  654. rgTreeInfo[i].hItem = TV_InsertItem(hWndTable, rgTreeInfo[i].hParent, TVI_SORT, szBuffer, (LONG)i, ICON_SYSTABLE, ICON_SYSTABLE);
  655. else
  656. rgTreeInfo[i].hItem = TV_InsertItem(hWndTable, rgTreeInfo[i].hParent, TVI_SORT, szBuffer, (LONG)i, ICON_SYNONYM, ICON_SYNONYM);
  657. }
  658. // If there was a previous selection, select it again on Back
  659. bFound = FALSE;
  660.     if(pCFromTable->m_TableInfo.wszTableName[0])
  661. {
  662. //Find the previously selected TableName
  663. //With TreeView controls there is no "Find" method as in ListView controls!
  664. //So we have to simulate our own find, by seraching for the TableName
  665. for(i=0; i<m_cTables; i++)
  666. {
  667. if(memcmp(&m_rgTableInfo[i], &pCFromTable->m_TableInfo, sizeof(TABLEINFO))==0)
  668. {
  669. bFound = TRUE;
  670. //Select Table in the TreeView control
  671. SendMessage(hWndTable, TVM_SELECTITEM, (WPARAM)TVGN_CARET, (LPARAM)rgTreeInfo[i].hItem);
  672. ResetColInfo(GetDlgItem(m_hWnd, IDL_COLUMNS));
  673. break;
  674. }
  675. }
  676. }
  677. if(!bFound)
  678. {
  679. //Reset TableInfo
  680. memset(&pCFromTable->m_TableInfo, 0, sizeof(TABLEINFO));
  681. //Otheriwse if there was no previous selection, default to auto expand
  682. //the "TABLE" type, or the first type in the tree
  683. bFound = FALSE;
  684. for(i=0; i<m_cTables; i++)
  685. {
  686. if(wcscmp(m_rgTableInfo[i].wszType, L"TABLE")==0)
  687. {
  688. bFound = TRUE;
  689. SendMessage(hWndTable, TVM_ENSUREVISIBLE, (WPARAM)0, (LPARAM)rgTreeInfo[i].hItem);
  690. break;
  691. }
  692. }
  693. if(!bFound && m_cTables)
  694. SendMessage(hWndTable, TVM_ENSUREVISIBLE, (WPARAM)0, (LPARAM)rgTreeInfo[0].hItem);
  695. }
  696. CLEANUP:
  697. if(hAccessor && pIAccessor)
  698. XTEST(pIAccessor->ReleaseAccessor(hAccessor,NULL));
  699. SAFE_RELEASE(pIRowset);
  700. SAFE_RELEASE(pIAccessor);
  701. SAFE_FREE(rgTreeInfo);
  702. SAFE_FREE(rghRows);
  703. return hr==S_OK;
  704. }
  705. /////////////////////////////////////////////////////////////////////////////
  706. // BOOL CS1Dialog::ResetColInfo
  707. //
  708. /////////////////////////////////////////////////////////////////////////////
  709. BOOL CS1Dialog::ResetColInfo(HWND hWndCol)
  710. {
  711. HRESULT hr;
  712. CHAR szBuffer[MAX_NAME_LEN];
  713. ULONG i;
  714. LONG    lFoundColumn;
  715. CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
  716. IOpenRowset* pIOpenRowset = pCFromTable->m_pCDataSource->m_pIOpenRowset;
  717. //Save the currently selected columns
  718. ULONG cSelColumns = pCFromTable->m_cColumns;
  719. COLDESC* rgSelColDesc = pCFromTable->m_rgColDesc;
  720. //Reset current Window Column ListView
  721. SendMessage(hWndCol, LVM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0L);
  722. // Get a list of columns based on the selected table
  723. pCFromTable->m_cColumns = 0;
  724. pCFromTable->m_rgColDesc = NULL;
  725. QTESTC(hr = pCFromTable->GetColInfo(IDR_PARAM_SETS));
  726. //Loop through all columns and update window
  727. for(i=0; i<pCFromTable->m_cColumns; i++)
  728. {
  729. COLDESC* pColDesc = &pCFromTable->m_rgColDesc[i];
  730. //COLNAME (item)
  731. ConvertToMBCS(pColDesc->wszColName, szBuffer, MAX_NAME_LEN);
  732. LV_InsertItem(hWndCol, i, COL_COLNAME, szBuffer, 0, pColDesc->dwFlags & (DBCOLUMNFLAGS_WRITE | DBCOLUMNFLAGS_WRITEUNKNOWN) ? ((pColDesc->dwFlags & DBCOLUMNFLAGS_ISLONG) ? ICON_LONG : ICON_COLUMN) : ICON_READONLY);
  733. //COLTYPE (subitem)
  734. ConvertToMBCS(GetDBTypeName(pColDesc->wType), szBuffer, MAX_NAME_LEN);
  735. LV_InsertItem(hWndCol, i, COL_COLTYPE, szBuffer);
  736. //Ordinal (SubItem)
  737. sprintf(szBuffer, "%d", pColDesc->iOrdinal);
  738. LV_InsertItem(hWndCol, i, COL_COLORDINAL, szBuffer);
  739. //ColumnSize (SubItem)
  740. sprintf(szBuffer, "%d", pColDesc->ulColumnSize);
  741. LV_InsertItem(hWndCol, i, COL_COLSIZE, szBuffer);
  742. //Precision (SubItem)
  743. sprintf(szBuffer, "%d", pColDesc->bPrecision);
  744. LV_InsertItem(hWndCol, i, COL_COLPREC, szBuffer);
  745. //Scale (SubItem)
  746. sprintf(szBuffer, "%d", pColDesc->bScale);
  747. LV_InsertItem(hWndCol, i, COL_COLSCALE, szBuffer);
  748. //FLAGS (SubItem)
  749. LV_InsertItem(hWndCol, i, COL_COLISFIXED, pColDesc->dwFlags & DBCOLUMNFLAGS_ISFIXEDLENGTH ? "TRUE" : "FALSE");
  750. LV_InsertItem(hWndCol, i, COL_COLISLONG, pColDesc->dwFlags & DBCOLUMNFLAGS_ISLONG ? "TRUE" : "FALSE");
  751. LV_InsertItem(hWndCol, i, COL_COLISNULLABLE, pColDesc->dwFlags & DBCOLUMNFLAGS_ISNULLABLE ? "TRUE" : "FALSE");
  752. LV_InsertItem(hWndCol, i, COL_COLWRITE, pColDesc->dwFlags & (DBCOLUMNFLAGS_WRITE | DBCOLUMNFLAGS_WRITEUNKNOWN) ? "TRUE" : "FALSE");
  753. LV_InsertItem(hWndCol, i, COL_COLISROWID, pColDesc->dwFlags & DBCOLUMNFLAGS_ISROWID ? "TRUE" : "FALSE");
  754. LV_InsertItem(hWndCol, i, COL_COLISROWVER, pColDesc->dwFlags & DBCOLUMNFLAGS_ISROWVER ? "TRUE" : "FALSE");
  755. }
  756. // If there is an existing columns list (only on Back or error), then
  757. // the user already has a list so use it.
  758. lFoundColumn = -1;
  759. for(i=0; i<cSelColumns; i++) 
  760. {
  761. //Find the Column Name in the Window List
  762. ConvertToMBCS(rgSelColDesc[i].wszColName, szBuffer, MAX_NAME_LEN);
  763. lFoundColumn = LV_FindItem(hWndCol, szBuffer, lFoundColumn);
  764. //Select the Column Name if found in the list, and bring into view
  765. if(lFoundColumn != LVM_ERR)
  766. {
  767. LV_SetItemState(hWndCol, lFoundColumn, COL_COLNAME, LVIS_SELECTED, LVIS_SELECTED);
  768. //Ensure that the first item is Visible
  769. if(i==0)
  770. SendMessage(hWndCol, LVM_ENSUREVISIBLE, (WPARAM)lFoundColumn, (LPARAM)FALSE);
  771. }
  772. }
  773. //Otherwise, just select all as default
  774. if(cSelColumns == 0)
  775. {
  776. for(i=0; i<pCFromTable->m_cColumns; i++)
  777. LV_SetItemState(hWndCol, i, COL_COLNAME, LVIS_SELECTED, LVIS_SELECTED);
  778. }
  779. CLEANUP:
  780. SAFE_FREE(rgSelColDesc);
  781. return hr==S_OK;
  782. }
  783. /////////////////////////////////////////////////////////////////////////////
  784. // BOOL CS1Dialog::ChangeTableName
  785. //
  786. /////////////////////////////////////////////////////////////////////////////
  787. BOOL CS1Dialog::ChangeTableName(LONG iIndex)
  788. {
  789. CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
  790. CTable* pCToTable = m_pCTableCopy->m_pCToTable;
  791. //Index must fall with the m_rgTableInfo array range
  792. //Otherwise we have selected a "tree-folder" and need to free the column list
  793. if(iIndex < 0 || iIndex >= (LONG)m_cTables)
  794. {
  795. //Resest TableName
  796. memset(&pCFromTable->m_TableInfo, 0, sizeof(TABLEINFO));
  797. //Reset current Window Column ListView
  798. SendMessage(GetDlgItem(m_hWnd, IDL_COLUMNS), LVM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0L);
  799. return FALSE;
  800. }
  801. //Only change the TableName if not equal to "Enter - <TableTerm>"
  802. if(wcsstr(m_rgTableInfo[iIndex].wszTableName, L"Enter - "))
  803. return FALSE;
  804. //TableInfo
  805. memcpy(&pCFromTable->m_TableInfo, &m_rgTableInfo[iIndex], sizeof(TABLEINFO));
  806. //QualifiedTableName syntax
  807. // #1.  TableName
  808. // #2.  Owner.TableName (always a ".")
  809. // #3.  Catalog[CatalogSeperator]TableName
  810. // #4.  Catalog[CatalogSeperator]Owner.TableName
  811. if(pCFromTable->m_TableInfo.wszSchemaName[0])
  812. swprintf(pCFromTable->m_wszQualTableName, L"%s.%s", pCFromTable->m_TableInfo.wszSchemaName, pCFromTable->m_TableInfo.wszTableName);
  813. else
  814. wcscpy(pCFromTable->m_wszQualTableName, pCFromTable->m_TableInfo.wszTableName);
  815. //Free the current columns list, since the new 
  816. //table will have diffent columns
  817. pCFromTable->m_cColumns = 0;
  818. SAFE_FREE(pCFromTable->m_rgColDesc);
  819. //Reset the column list, since we have a new table
  820. ResetColInfo(GetDlgItem(m_hWnd, IDL_COLUMNS));
  821. //Reset the index list, since we have a new table
  822. pCFromTable->m_cIndexes = 0;
  823. SAFE_FREE(pCFromTable->m_rgIndexInfo);
  824. //Reset the "To" table, since we have a new table
  825. memset(&pCToTable->m_TableInfo, 0, sizeof(TABLEINFO));
  826. return TRUE;
  827. }