Где воздух гор - там тишина снегов, молчание камней и дремлет сила

Программирование Windows

Создание программы - MySQL DatabaseBrowser

2018-03-09 08:21:18







Сейчас использование баз данных, в то числе и удаленных стало обычной и повседневной практикой. Очень часто используется и СУБД MySQL – свободной распространяемая система управления базами данных. В основном она используется для малых и средних предприятий, где успешно решает многие задачи. Ее бесплатность, доступность, стабильность в работе и прочие характеристики позволяет говорить об это СУБД как о массовой альтернативе таких баз как InterBase или SyBase. Последние версии этой программы, существенно расширяющие ее возможности предлагают решение многих проблем, с которым сталкиваются как администратор баз данных, так и обычный пользователь.

 
Однако, существуют так же и проблемы при работе с Windows, как обязательное наличие драйверов ODBC   для MySQL, если СУБД работает в этой среде. Стандартный клиент для MySQL не является удобным в настоящее время, так как является консольной программой. Опять же, требуется как минимум наличие установленной копии программы MySQL сервер на компьютере пользователя. Просмотр данных и простое редактирование также в стандартном клиенте не отвечает современным требованиям к интерфейсу. Решение целого ряда повседневных задач, предполагает стандартизацию  пользовательского интерфейса и  создание удобного юзабилити.
 
 Поэтому мы пришли к необходимости создания собственного клиентского приложения  Целью данного проекта является создание программы, которая бы позволяла выполнять наиболее общие операции с СУБД MySQL в операционной системе Windows, и при это не требовала наличия и настройки ODBC драйвера. Обычно это не умеет делать средний пользователь, и следовательно здесь требуется помощь администратора, что создает дополнительные трудности и самое главное, потерю рабочего времени.  Кроме того, эта программа должна уметь соединяться и работать с удаленным MySQL сервером.  Сам проект на данном этапе не является окончательной версией программы, поэтому реализуется с наиболее общими возможностями.
 
Далее будет описано шаг за шагом процесс создания проекта и с примерами исходного кода.
 
 
 
В начале мы создаем шаблон проекта. Для этого мы в Visual Studio выбираем «MFC APPWizard» и вводим название проекта «Myslqlone» . Далее, «Шаге1» выбираем «Single Document». В «Шаге2» и в «Шаге3» не меняем ничего,
в «Шаге 4» отключаем «Printing and Print Preview» и переключаем радиобокс на «Internet Explorer Rebars”. В «Шаге 5» выбираем из 2 радиобоксов «Windows Explorer». На конец, в «Шаге 6» нажимаем кнопку «Finish». Выбранный нами тип проекта приложения наиболее полно отвечает решению поставленной задачи. В нем находятся изначально 2 удобных класса, «CleftView”, который
является потомком класса «CtreeCtrl» в нашем случае, «CmysqloneView», который в свою очередь наследует от «ClistView», что очень удобно и ускоряет процесс разработки проекта. Оба эти класса могут использовать возможности
контролов ClistCtrl и CtreeCTrl, от которых они порождены. Данные обстоятельства в последствии будут нами постоянно использоваться в этом проекте.Все дальнейшие действия разбиты на этапы и описываются здесь ниже.


1. Копируем 2 файла в папку проекта: «libmysql.dll» и «libmysql.lib» из папки MySQL Server 4.1/lib/. Затем подключаем к проекту файл «libmysql.lib». Нам потребуется этий файлы для обеспечения работы программы и доступа к MySQL API функциям. Мы будем использовать MySQL C API функции,
как наиболее стабильно работающие и обеспечивающие полный сервис.

2. Затем копируем все заголовочные файлы из директории MySQL Server 4.1/include/ все заголовочные файлы в директориюVC /include/ Visual Studio.
Это также необходимо для создания и компиляции проекта.

3. Подключаем в файл “mysql.h” к файлу «stdafx.h» :
#include "mysql.h"

4. Создаем переменную класса CImageList m_TreeImages в классе
«CleftView.cpp» Она будет использована для создания списка картинок, которые будут в свою очередь использованы в создаваемом объекте типа CtreeCtrl.

5. Создаем в файле ресурсов новый ресурс.


6. Создаем в классе «CleftView.cpp» новый метод void FillTree():
void CLeftView::FillTree()
{
CTreeCtrl & m_tree = GetTreeCtrl();
m_tree.DeleteAllItems();

m_tree.SetImageList(&m_TreeImages, TVSIL_NORMAL);


HTREEITEM hRoot;

CMysqloneDoc* pDoc = GetDocument();

for (int i = 0; i < pDoc->m_available_bases.GetSize(); i++)
{
hRoot = m_tree.InsertItem(pDoc->m_available_bases[i], 0, 1);
}


}

7. Создаем в методе класса «CleftView.cpp» :OnInitialUpdate()
объект класса CimageList:

m_TreeImages.Create(IDB_BITMAP1, 16, 1, RGB(255, 255, 255));
Это создает список пиктограмм для CtreeCtrl

8. Добавляем в этот же класс метод OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) для обработки события смены элементов списка.

9. Вставляемвэтотметодтакойкод:

void CLeftView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

CTreeCtrl & m_tree = GetTreeCtrl();
CMysqloneDoc* pDoc = GetDocument();
if (!pDoc->connected) {return;}
pDoc->current_table = "";
HTREEITEM nodSelected = m_tree.GetSelectedItem();

if (nodSelected>=0) {

CString strSelected=m_tree.GetItemText(nodSelected);
GetDocument()->SetTitle(strSelected);
}


HTREEITEM parent;
parent = m_tree.GetParentItem (nodSelected);
if (parent) {
pDoc->current_table = m_tree.GetItemText (nodSelected);

pDoc->UpdateAllViews (this);
return;
}



HTREEITEM child;
while (child = m_tree.GetChildItem (nodSelected)) {
m_tree.DeleteItem (child);
}



CString base_name = m_tree.GetItemText (nodSelected);
pDoc->current_base = base_name;

MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
MYSQL_RES * my_res;
MYSQL_ROW row;
CString sql;

mysql_select_db (mysql, base_name.GetBuffer(125));
if (mysql_query (mysql, "SHOW TABLES")) {
AfxMessageBox ("Query SHOW databases failed");
return;
}
my_res = mysql_store_result(mysql);
while (row = mysql_fetch_row (my_res)) {
char buffer[255];
strcpy (buffer, row[0]);
m_tree.InsertItem (_T(buffer), nodSelected);
}
mysql_free_result (my_res);


*pResult = 0;
}


10. Добавляем новый ресурс – диалоговое окно. Туда вставляем 3 поля редактирования, одному из них в стилях проставляем стиль: «password» . Далее мы заходи в Class Wizard и создаем новый класс для данного диалога. Назовем его «CLoginDlg». Он будет наследоваться от класса CDialog. Далее к каждому из полей редактирования создаем переменные типа Cstring. Это будут переменные этого класса для ввода данных по соединению с MySQL сервером.

11. Затем мы создаем переменную типа MYSQL mysql для класса «CmysqloneApp.cpp», это класс приложения. Эта переменная будет использоваться нами далее везде в программе для доступа к функциям MySQL.
Затем создаем в этом же классе новый метод для соединения с сервером баз данных типа BOOL ConnectToDb(). Вот его код:


BOOL CMysqloneApp::ConnectToDb()
{
CLoginDlg dlg;

while (dlg.DoModal()== IDOK) {
if(!mysql_init(&mysql)){AfxMessageBox ("Can't make initialization to mysql server!");}
if(mysql_real_connect(&mysql,dlg.m_host, dlg.m_login,dlg.m_password,NULL,0,NULL,0)){
return TRUE;
}
}
return FALSE;

}
В этом методе вызывается диалоговое окно CloginDlg, чтобы считать введенные пользователем данные и выполнить соединение с MySQL сервером. Данные пользователя хранятся в специальном файле, с расширением «.lgn», который предоставляет администратор. Нижеприводитсякодметодаподключенияксерверубазданных:
void CLoginDlg::OnBnClickedLogin()
{
UpdateData();

char login[35];
char password[25];
char host[255];
FILE *file;
bool valid_login = false;

if( m_login =="")
{
AfxMessageBox("You must provide a username and password or click Cancel!");
return;
}
if( m_password =="")
{
AfxMessageBox("Invalid login entered");
return;
}


if( m_host =="")
{
AfxMessageBox("Enter host name, please");
return;
}

try {

file = fopen("database.lgn", "r");


while( !feof(file) )
{

fscanf(file, "%s", login);


if( strcmp((LPCTSTR)m_login, login) == 0 )
{

fscanf(file, "%s", password);


if( strcmp((LPCTSTR)m_password, password) == 0 )
{
valid_login = true;
}
else
valid_login = false;
}
}
if( valid_login == true )
OnOK();
else
{
AfxMessageBox("Invalid entry data entered! Please try again");

}

fclose(file);
}
catch(...)
{
AfxMessageBox("Could not validate entered information to connect with MySQL database");
}

UpdateData(FALSE);

}


12. Подключаемзаголовочныйфайлкласса «CloginDlg.cpp» – «LoginDlg.h» к
кфайлукласса «CMysqloneApp»-«mysqlone.cpp»

#include "LoginDlg.h"

13. Создаем еще один метод для этого же класса типа void ExecuteSQL(CString sql). Он будет использоваться для выполнения запросов к MySQL серверу.
Вот его код:

void CMysqloneApp::ExecuteSQL(CString sql)
{

mysql_query (&mysql, sql);

}

Он также будет использоваться повсеместно в работе программы.

14. Затем мы создаем новые переменные для класса «CmysqloneDoc.cpp»
CStringArray m_available_bases; //текстовой массив списка доступных .//баз.
CString current_base; //переменная строкового типа для имени текущей //базы
CString current_table; //строковая переменная для имени текущей таблицы
bool connected;// переменная булевого типа для состояния соединения с //MySQL сервером.

15. На конец, вставляем следующий код вызова метода ConnectToDb() в
«CMysqloneApp»-«mysqlone.cpp» в метод InitInstance():

SetRegistryKey(_T("MySQLOne- MySQL Database Browser"));

LoadStdProfileSettings(); // Load standard INI file options (including MRU)

//После этих строк.

if (!ConnectToDb()) {
AfxMessageBox ("Could not connect to base\nQuitting");
return FALSE;
}

Метод ConnectToDb() будет вызываться при запуске программы, а поскольку он булевого типа, то про возращении этим методом FALSE программа не будет работать.
Теперь добавим еще один метод, который будет выбирать базу данных для дальнейшего использования.


void CMysqloneApp::ChangeCurrentBase(CString newBaseName)
{
mysql_select_db (&mysql, newBaseName);
}

16. Далее мы переходим в класс «CleftView.cpp» и через Class Wizard добавляем туда метод OnUpdate. Это один из поддерживаемых представлением методов, который нам нужно переопределить таким образом:

void CLeftView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{

CTreeCtrl & m_tree = GetTreeCtrl();
CMysqloneDoc* pDoc = GetDocument();
if (!pDoc->connected) {
m_tree.DeleteAllItems();
return;
}
FeelTree();

}


17. Затеммыпереходимсноваккласс «CmysqloneDoc.cpp» ипереопределяемметод OnNewDocument():


BOOL CMysqloneDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;

current_table = "";

MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
MYSQL_RES * my_res;
MYSQL_ROW row;
if (mysql_query (mysql, "SHOW databases")) {
AfxMessageBox ("Query SHOW databases failed");
return TRUE;
}
my_res = mysql_store_result(mysql);
int num = mysql_num_rows (my_res);

m_available_bases.RemoveAll();
while (row = mysql_fetch_row (my_res)) {
m_available_bases.Add (row[0]);
}

mysql_free_result (my_res);
current_base = "";
return TRUE;

}


18. Теперь переходим в класс «CmysqloneView.cpp», где добавляем в метод этого класса OnInitialUpdate() следующий код для создания объекта типа ClistCTrl и задания его стилей отображения.

void CMysqloneView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
CListCtrl &m_list = GetListCtrl();
m_list.ModifyStyle(NULL, LVS_REPORT);
m_list.SetExtendedStyle (LVS_EX_GRIDLINES );


}


19. Далеемыидемсновав Class Wizard итамдобавляемвкласс «CmysqloneView.cpp» метод OnUpdate ипомещаемтудатакойкод:

void CMysqloneView::OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/)
{
CListCtrl &m_list = GetListCtrl();
CMysqloneDoc* pDoc = GetDocument();

if (!pDoc->connected) {
m_list.DeleteAllItems ();
while(m_list.DeleteColumn(0));
return;
}
if (pDoc->current_table == "") return;
m_list.DeleteAllItems();
while(m_list.DeleteColumn(0));

MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
MYSQL_RES * my_res;
MYSQL_ROW row;
CString sql;
sql="SHOW COLUMNS IN ";
sql += pDoc->current_table;
mysql_query (mysql, sql);
my_res = mysql_store_result (mysql);
int i = 0;
int counter = 0;
while (row = mysql_fetch_row (my_res)) {
m_list.InsertColumn (i, row[0], LVCFMT_LEFT, 100);
i++;
}
counter = i;
mysql_free_result (my_res);


sql = "SELECT * FROM ";
sql += pDoc->current_table;
mysql_query (mysql, sql);
my_res = mysql_store_result (mysql);
i = 0;
LVITEM item;
item.mask = LVIF_TEXT;
while (row = mysql_fetch_row (my_res)) {
item.iItem = i;
item.iSubItem = 0;
item.pszText = row[0];
m_list.InsertItem (&item);
for (int z = 1; z < counter; z++) {
item.iSubItem = z;
item.pszText = row[z];
m_list.SetItem (&item);
}

i++;
}

}


Этотметодбудетиспользоватьсядляотображениявправойчастиокнаструктурыданных, полученныхврезультатезапросекбазеданных.
Фактически, это и будет главное просмотровое окно программы, отображающие данные и структуру таблиц баз данных.


20. Теперь мы снова идем во вкладку «Resources» и добавляем новый ресурс – диалоговое окно. Это окно будет использоваться для создания новой базы данных. Мы вводим туда новое текстовое поле типа CEdit и СStatic, для создания текстового заголовка: «New Database Name». Создаем в Class Wizarde новый класс «CNewDatabaseDlg». К текстовому полю CEdit подключаем переменную типа CString - «m_newdatabase». Эта переменная для задания нового имени вновь создаваемой базы данных.

21. Переопределяем метод этого класса OnOK() для исполнения запроса к MySQL серверу по созданию новой базы.

void CNewDatabase::OnOK()
{
UpdateData(TRUE);
CString sql="CREATE DATABASE ";
sql +=m_newdatabase;
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (sql);

CDialog::OnOK();
}


22. Подключаем заголовочный файл нового диалогового «CreateNewTableDlg.h» к классу «CleftView.срр» для последующей обработки командой меню.


23. Теперь переходим опять во вкладку «Resources» и добавляем новое диалоговое окно. На этот раз в нем будет окно для исполнения запросов к базе данных. Мы добавляем туда следующие контролы: ССombox – сюда мы будем вводить SQL запрос, CListBox - это будет форма для отображения списка доступных нам баз данных и CListCtrl - в нем будут отображаться результаты SQL запросов. Итак, мы создаем 2 переменных класса:
CListBox m_listbox и CListCtrl m_list.

24. Затем мы добавляем новый метод к этому классу диалога- void AddStr(). Этот метод будет получать строковую переменную, введенную в CComboBox . Далее код этого метода:

void CSqlQueryDlg::AddStr()
{

CComboBox *Box;

Box = (CComboBox *)(this->GetDlgItem(IDC_COMBO1));

Box->AddString(m_sql);
}



25. Теперь нам необходимо заполнить список базами данных, которыей находятся в данный момент на сервере MySQL. Для этого мы подключаем и переопределяем метод OnInitDialog(). В нем мы заполняем список CListBox, который буджет показываться при запуске этого окна.

BOOL CSqlQueryDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// TODO: Add extra initialization here
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
MYSQL_RES * my_res;
MYSQL_ROW row;
CString data_sql="SHOW DATABASES";
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (data_sql);

my_res = mysql_store_result(mysql);
while (row = mysql_fetch_row (my_res)) {
char buffer[255];
strcpy (buffer, row[0]);
m_listbox.AddString(_T(buffer));
}

mysql_free_result (my_res);

return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}


26. Затем, мы переопределяем метод OnOK() у этого класса, чтобы выполнить SQL запрос.


void CSqlQueryDlg::OnOK()
{
UpdateData();

MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);

CString basename;
m_listbox.GetText (m_listbox.GetCurSel(), basename);
((CMysqloneApp*)AfxGetApp())->ChangeCurrentBase (basename);
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (m_sql);

m_list.DeleteAllItems ();


while(m_list.DeleteColumn(0));
MYSQL_RES * my_res;
MYSQL_ROW row;
mysql_query (mysql, m_sql);
my_res = mysql_store_result (mysql);

int cols = mysql_num_fields (my_res);
int counter ;
for (counter = 0; counter < cols; counter++) {
m_list.InsertColumn (counter, "Data", LVCFMT_LEFT, 50);
}

counter = cols;
LVITEM item;
item.mask = LVIF_TEXT;
int i = 0;
while (row = mysql_fetch_row (my_res)) {
item.iItem = i;
item.iSubItem = 0;
item.pszText = row[0];
m_list.InsertItem (&item);
for (int z = 1; z < counter; z++) {
item.iSubItem = z;
item.pszText = row[z];
m_list.SetItem (&item);
}

i++;

}

mysql_free_result (my_res);


//CDialog::OnOK();
}

Заметим, что последняя строка кода закомментирована, чтобы OnOk() не закрывал это окно по завершению работы.
 
27. Теперь добавим новую кнопку в это диалоговое окно и переименуем ее
 
заголовок в «Clear» и затем создадим для нее обработчик. Этот метод будет
 
очищать переменную CListCtrl m_list после исполнения запроса к базе данных.
 
Код метода ниже по тексту.
 
 
 
void CSqlQueryDlg::OnClear()
 
{
 
m_list.DeleteAllItems ();
 
UpdateData(FALSE);
 
}
 
28. На конец, мы снова подключаем заголовочный файл данного класса диалогового окна «CListCtrl m_list.h» к классу «CleftView.срр» для последующей обработки командой меню.
 
29. Снова переходим во вкладку «Resources» и добавляем новое диалоговое окно. В этом случае это будет окно для удаления базе данных, которые доступны нам . Мы добавляем сюда 2 контрола: CStatic, в который вводим следующий текст: «Database Name» и CListBox m_listbox, в котором список баз данных будет отображаться. Затем мы добавляем и переопределяем метод класса OnInitDialog, в котором список баз будет заполняться.
 
BOOL CDeleteDatabaseDlg::OnInitDialog()
 
{
 
CDialog::OnInitDialog();
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
MYSQL_RES * my_res;
 
MYSQL_ROW row;
 
CString data_sql="SHOW DATABASES";
 
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (data_sql);
 
my_res = mysql_store_result(mysql);
 
while (row = mysql_fetch_row (my_res)) {
 
char buffer[255];
 
strcpy (buffer, row[0]);
 
m_listbox.AddString(_T(buffer));
 
}
 
mysql_free_result (my_res);
 
return TRUE; // return TRUE unless you set the focus to a control
 
// EXCEPTION: OCX Property Pages should return FALSE
 
}
 
Строка запроса будет отображаться в MessageBox, чтобы видеть совершаемое действие.
 
30. Затем мы переопределяем метод класса OnOk() для исполнения
 
собственно запроса к базе данных. Вот его код:
 
void CDeleteDatabaseDlg::OnOK()
 
{
 
UpdateData(TRUE);
 
CString item;
 
int index=m_listbox.GetCurSel();
 
m_listbox.GetText(index,item);
 
CString sql="DROP DATABASE ";
 
sql +=item;
 
m_delete=sql;
 
AfxMessageBox(m_delete);
 
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (sql);
 
CDialog::OnOK();
 
}
 
31. Опятьже, подключаем «DeleteDatabaseDlg.h» файлзаголовкакклассу «CLeftView.cpp» дляиспользованиявобработчикеменю.
 
32. Теперь мы идем опять во вкладку «Resources» и там находим в папке «Menu» ресурс меню проекта - «IDR_MAINFRAME». Мы удаляем все стандартные опции меню, за исключением «Exit» и создаем свои пункты меню и идентификаторы для них. Получаются такие команды меню и идентификаторы:
 
«Сreate New Table» (ID_NEW_DATABASE), «MySQL Query»( ID_MYSQL_QUERY), «Drop Database»( ID_DATA_DROPDATABASE) и
 
«See Last Insert/Alter SQL Query»( ID_DATA_SEELASTSQLQUERY). Эта опция меню будет описана позднее. Затем мы создаем для них обработчики в классе «CLeftView.cpp». Далее их полный код:
 
void CLeftView::OnNewDatabase()
 
{
 
CNewDatabase dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.InsertItem(dlg.m_newdatabase, TVI_ROOT);
 
m_tree.SelectItem(hitem);
 
}
 
}
 
void CLeftView::OnDataDropdatabase()
 
{
 
CDeleteDatabaseDlg dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
CString selected=m_tree.GetItemText(hitem);
 
m_tree.DeleteItem(hitem);
 
}
 
}
 
void CLeftView::OnNewTable()
 
{
 
CCreateNewTableDlg dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
HTREEITEM childitem=m_tree.GetChildItem(hitem);
 
childitem = m_tree.InsertItem(dlg.m_newtable, TVI_FIRST);
 
m_tree.SelectItem(childitem);
 
}
 
}
 
void CLeftView::OnMysqlQuery()
 
{
 
CSqlQueryDlg dlg;
 
if (dlg.DoModal() == IDOK ){
 
dlg.OnOK();
 
}
 
}
 
void CLeftView::OnDataSeelastsqlquery()
 
{
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
const char* last_query;
 
CString noresult;
 
CString temp;
 
last_query=mysql_info(mysql);
 
temp=(CString)last_query;
 
if (temp=="NULL") {
 
noresult="No any SQL request was done till now";
 
AfxMessageBox(noresult);
 
}
 
else {
 
AfxMessageBox(temp);
 
}
 
}
 
На последнем методе остановимся подробнее. Остальные обработчики команд меню используют описанные выше диалоговые классы. А этот метод служит для получения информации о последнем запросе типа INSERT/ALTER к базе данных. Такая информация полезна при коллективной работе с сервером баз данных, так как наиболее быстро позволяет видеть последние изменения данных без необходимости исполнения запросов к таблице.
 
33. Теперь перейдем во вкладку «Resources» и выбираем «IDD_ABOUTBOX». Там мы добавляем 4 новых контрола типа Cstatic и распологаем их горизонтально, один над другим. Далее мы вводим в качестве заголовков «MySQL Host Name» и «MySQL Protocol Version» в оба верхних контрола. Первый нижний контрол мы переименовываем в
 
«IDC_INFO» и удаляем текст из него. Затем мы подключаем к нему переменную типа CString mysql_info. Во втором нижнем котроле мы убираем также весь текст в заголовке и подключаем к нему переменную типа int mysql_version. Обе эти переменные буду использоваться для
 
отображения информации в окне диалога «About».
 
34. Затем мы переопределяем метод OnAppAbout() этого класса для вызова 2 методов MySQL С API, которые в свою очередь выдадут ифнормацию о типе MySQL cсервера и его версии.
 
void CMysqloneApp::OnAppAbout()
 
{
 
CAboutDlg aboutDlg;
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
const char* host_info="";
 
int ver;
 
host_info=mysql_get_host_info(mysql);
 
ver=mysql_get_proto_info(mysql);
 
aboutDlg.mysql_info=(CString)host_info;
 
aboutDlg.mysql_version=ver;
 
aboutDlg.DoModal();
 
}
 
35. В меню “Help” добавляем новый пункт – “MySQL Info”
 
Здесь будет появляется модальное диалоговое окно, в котором
 
будет отображаться статус MySQL сервера. Для этого мы добавим туда еще в ресурсах новое диалоговое окно и назовем его «IDD_MYSQLINFODLG». Туда введем 5 новых элементов управления типа CStatic. Одно поле назовем «MySQL Server Status», а другие поля будут связаны с переменными типа CString и в последствии будут использоваться для отображения данных.
 
Далее переопределяем метод OnInitDialog() этого диалогового окна и вводим туда такой код:
 
BOOL CMySQLInfoDlg::OnInitDialog()
 
{
 
CDialog::OnInitDialog();
 
const char* result="";
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
result=mysql_stat(mysql);
 
CString temp=(CString)result;
 
m_mysqlinfo=temp;
 
UpdateData(FALSE);
 
return TRUE; // return TRUE unless you set the focus to a control
 
// EXCEPTION: OCX Property Pages should return FALSE
 
}
 
После добавляем обработчик в меню класса CMainFraime:
 
void CMainFrame::OnHelpMysqlinfo()
 
{
 
CMySQLInfoDlg dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
dlg.OnBnClickedExit();
 
}
 
}
 
36. Далее мы переходим снова редактор ресурсов, находим главное меню окна и добавляем туда новый пункт «Send E-Mail»
 
Затем подключаем его обработчик к классу CMysqloneDoc, редактируя его карту сообщений таким образом:
 
BEGIN_MESSAGE_MAP(CMysqloneDoc, CDocument)
 
//{{AFX_MSG_MAP(CMysqloneDoc)
 
// NOTE - the ClassWizard will add and remove mapping macros here.
 
// DO NOT EDIT what you see in these blocks of generated code!
 
//}}AFX_MSG_MAP
 
ON_COMMAND(ID_FILE_SEND_MAIL, OnFileSendMail)
 
ON_UPDATE_COMMAND_UI(ID_FILE_SEND_MAIL, OnUpdateFileSendMail)
 
END_MESSAGE_MAP()
 
Это позволит нам слать сообщения по электронной почте прямо из программы.
 
37. Снова возвращаемся в редактор ресурсов, к главному меню и вставляем туда такой пункт «Data Optimization». Обработчик для него ставим в классе CLeftView.
 
void CLeftView::OnDataDataoptimization()
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
HTREEITEM childitem=m_tree.GetChildItem(hitem);
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
CMysqloneDoc* pDoc = GetDocument();
 
CString base_name=m_tree.GetItemText(hitem);
 
CString strSelected=m_tree.GetItemText(childitem);
 
pDoc->current_base=base_name;
 
CString sql="OPTIMIZE TABLE ";
 
mysql_select_db(mysql,base_name.GetBuffer(255));
 
sql+=strSelected;
 
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (sql);
 
pDoc->UpdateAllViews (NULL);
 
}
 
Здесь мы сможем легко производить оптимизацию выбранной таблицы базы.
 
38. . Снова возвращаемся в редактор ресурсов, к главному меню и вставляем туда такой пункт «Empty All Data». Обработчик для него ставим в классе также CLeftView.
 
void CLeftView::OnDataCreatenewtable()
 
{
 
CCreateNewTableDlg dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
HTREEITEM childitem=m_tree.GetChildItem(hitem);
 
// childitem = m_tree.InsertItem(dlg.m_newtable, TVI_FIRST);
 
m_tree.SelectItem(childitem);
 
}
 
}
 
void CLeftView::OnDataEmptyalldata()
 
{
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
CString sql="DELETE FROM ";
 
HTREEITEM nodSelected = m_tree.GetSelectedItem();
 
if (nodSelected>=0) {
 
CString strSelected=m_tree.GetItemText(nodSelected);
 
sql +=strSelected;
 
AfxMessageBox("Are you sure to wish to delete ALL data from "+ strSelected,MB_OKCANCEL|MB_ICONQUESTION );
 
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (sql);
 
m_tree.DeleteItem(nodSelected);
 
}
 
}
 
Мы очищаем таблицу от данных при помощи этой команды меню.
 
На конец, запускаем программу и послу успешной компиляции мы получим диалоговое окно для ввода информации. Затем мы увидим список
 
баз в виде дерева и таблицы, которые можно просмотреть структуру и сами данные в таблицах баз данных. С помощью
 
команд меню можно создать и удалить базу, выполнить любой SQL запрос к любой таблице (при наличии у пользователя необходимых полномочий ), послать сообщение электронной почты, посмотреть последние обновления.
 
Таким образом, мы получили программу, с помощью которой можно выполнять базовый набор операций сервером MySQL и при этом не требуется поддержка и настройка ODBC драйвера. В дальнейшем проект может быть значительно расширен и улучшен.
 
Исходный код программы.
 
#include "afxwin.h"
 
#if !defined(AFX_DELETEDATABASEDLG_H__16ACDEC0_DE9D_11D9_A8EF_929CCA0FC15A__INCLUDED_)
 
#define AFX_DELETEDATABASEDLG_H__16ACDEC0_DE9D_11D9_A8EF_929CCA0FC15A__INCLUDED_
 
#if _MSC_VER > 1000
 
#pragma once
 
#endif // _MSC_VER > 1000
 
// DeleteDatabaseDlg.h : header file
 
//
 
/////////////////////////////////////////////////////////////////////////////
 
// CDeleteDatabaseDlg dialog
 
class CDeleteDatabaseDlg : public CDialog
 
{
 
// Construction
 
public:
 
CDeleteDatabaseDlg(CWnd* pParent = NULL); // standard constructor
 
// Dialog Data
 
//{{AFX_DATA(CDeleteDatabaseDlg)
 
enum { IDD = IDD_DIALOG4 };
 
//}}AFX_DATA
 
// Overrides
 
// ClassWizard generated virtual function overrides
 
//{{AFX_VIRTUAL(CDeleteDatabaseDlg)
 
protected:
 
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
 
//}}AFX_VIRTUAL
 
// Implementation
 
protected:
 
// Generated message map functions
 
//{{AFX_MSG(CDeleteDatabaseDlg)
 
virtual void OnOK();
 
virtual void OnCancel();
 
//}}AFX_MSG
 
DECLARE_MESSAGE_MAP()
 
public:
 
virtual BOOL OnInitDialog();
 
CListBox m_listbox;
 
CString m_delete;
 
};
 
//{{AFX_INSERT_LOCATION}}
 
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
 
#endif // !defined(AFX_DELETEDATABASEDLG_H__16ACDEC0_DE9D_11D9_A8EF_929CCA0FC15A__INCLUDED_)
 
// DeleteDatabaseDlg.cpp : implementation file
 
//
 
#include "stdafx.h"
 
#include "mysqlone.h"
 
#include "DeleteDatabaseDlg.h"
 
#include ".\deletedatabasedlg.h"
 
#ifdef _DEBUG
 
#define new DEBUG_NEW
 
#undef THIS_FILE
 
static char THIS_FILE[] = __FILE__;
 
#endif
 
/////////////////////////////////////////////////////////////////////////////
 
// CDeleteDatabaseDlg dialog
 
CDeleteDatabaseDlg::CDeleteDatabaseDlg(CWnd* pParent /*=NULL*/)
 
: CDialog(CDeleteDatabaseDlg::IDD, pParent)
 
, m_delete(_T(""))
 
{
 
//{{AFX_DATA_INIT(CDeleteDatabaseDlg)
 
m_delete = _T("");
 
//}}AFX_DATA_INIT
 
}
 
void CDeleteDatabaseDlg::DoDataExchange(CDataExchange* pDX)
 
{
 
CDialog::DoDataExchange(pDX);
 
//{{AFX_DATA_MAP(CDeleteDatabaseDlg)
 
//}}AFX_DATA_MAP
 
DDX_Control(pDX, IDC_LIST1, m_listbox);
 
}
 
BEGIN_MESSAGE_MAP(CDeleteDatabaseDlg, CDialog)
 
//{{AFX_MSG_MAP(CDeleteDatabaseDlg)
 
//}}AFX_MSG_MAP
 
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
 
// CDeleteDatabaseDlg message handlers
 
BOOL CDeleteDatabaseDlg::OnInitDialog()
 
{
 
CDialog::OnInitDialog();
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
MYSQL_RES * my_res;
 
MYSQL_ROW row;
 
CString data_sql="SHOW DATABASES";
 
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (data_sql);
 
my_res = mysql_store_result(mysql);
 
while (row = mysql_fetch_row (my_res)) {
 
char buffer[255];
 
strcpy (buffer, row[0]);
 
m_listbox.AddString(_T(buffer));
 
}
 
mysql_free_result (my_res);
 
return TRUE; // return TRUE unless you set the focus to a control
 
// EXCEPTION: OCX Property Pages should return FALSE
 
}
 
void CDeleteDatabaseDlg::OnOK()
 
{
 
UpdateData(TRUE);
 
CString item;
 
int index=m_listbox.GetCurSel();
 
m_listbox.GetText(index,item);
 
CString sql="DROP DATABASE ";
 
sql +=item;
 
m_delete=sql;
 
AfxMessageBox(m_delete,MB_ICONWARNING);
 
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (sql);
 
CDialog::OnOK();
 
}
 
void CDeleteDatabaseDlg::OnCancel()
 
{
 
// TODO: Add extra cleanup here
 
CDialog::OnCancel();
 
}
 
// LeftView.h : interface of the CLeftView class
 
//
 
/////////////////////////////////////////////////////////////////////////////
 
#if !defined(AFX_LEFTVIEW_H__58E6318E_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_)
 
#define AFX_LEFTVIEW_H__58E6318E_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_
 
#if _MSC_VER > 1000
 
#pragma once
 
#endif // _MSC_VER > 1000
 
class CMysqloneDoc;
 
class CLeftView : public CTreeView
 
{
 
protected: // create from serialization only
 
CLeftView();
 
DECLARE_DYNCREATE(CLeftView)
 
// Attributes
 
public:
 
CMysqloneDoc* GetDocument();
 
// Operations
 
public:
 
// Overrides
 
// ClassWizard generated virtual function overrides
 
//{{AFX_VIRTUAL(CLeftView)
 
public:
 
virtual void OnDraw(CDC* pDC); // overridden to draw this view
 
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
 
protected:
 
virtual void OnInitialUpdate(); // called first time after construct
 
virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
 
//}}AFX_VIRTUAL
 
// Implementation
 
public:
 
CImageList m_TreeImages;
 
void FillTree();
 
virtual ~CLeftView();
 
#ifdef _DEBUG
 
virtual void AssertValid() const;
 
virtual void Dump(CDumpContext& dc) const;
 
#endif
 
protected:
 
// Generated message map functions
 
protected:
 
//{{AFX_MSG(CLeftView)
 
afx_msg void OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult);
 
afx_msg void OnDataDropdatabase();
 
afx_msg void OnNewTable();
 
afx_msg void OnMysqlQuery();
 
//}}AFX_MSG
 
DECLARE_MESSAGE_MAP()
 
public:
 
afx_msg void OnNewDatabase();
 
afx_msg void OnDataSeelastsqlquery();
 
afx_msg void OnDataCreatenewtable();
 
afx_msg void OnDataEmptyalldata();
 
afx_msg void OnDataDataoptimization();
 
afx_msg void OnDataSearchdatain();
 
};
 
#ifndef _DEBUG // debug version in LeftView.cpp
 
inline CMysqloneDoc* CLeftView::GetDocument()
 
{ return (CMysqloneDoc*)m_pDocument; }
 
#endif
 
/////////////////////////////////////////////////////////////////////////////
 
//{{AFX_INSERT_LOCATION}}
 
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
 
#endif // !defined(AFX_LEFTVIEW_H__58E6318E_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_)
 
// LeftView.cpp : implementation of the CLeftView class
 
//
 
#include "stdafx.h"
 
#include "mysqlone.h"
 
#include "NewDatabase.h"
 
#include "CreateNewTableDlg.h"
 
#include "DeleteDatabaseDlg.h"
 
#include "SqlQueryDlg.h"
 
#include "mysqloneDoc.h"
 
#include "LeftView.h"
 
#include "mysqloneView.h"
 
#include ".\leftview.h"
 
#ifdef _DEBUG
 
#define new DEBUG_NEW
 
#undef THIS_FILE
 
static char THIS_FILE[] = __FILE__;
 
#endif
 
/////////////////////////////////////////////////////////////////////////////
 
// CLeftView
 
IMPLEMENT_DYNCREATE(CLeftView, CTreeView)
 
BEGIN_MESSAGE_MAP(CLeftView, CTreeView)
 
//{{AFX_MSG_MAP(CLeftView)
 
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
 
ON_COMMAND(ID_DATA_DROPDATABASE, OnDataDropdatabase)
 
ON_COMMAND(ID_NEW_TABLE, OnNewTable)
 
ON_COMMAND(ID_MYSQL_QUERY, OnMysqlQuery)
 
//}}AFX_MSG_MAP
 
ON_COMMAND(ID_NEW_DATABASE, OnNewDatabase)
 
ON_COMMAND(ID_DATA_SEELASTSQLQUERY, OnDataSeelastsqlquery)
 
ON_COMMAND(ID_DATA_CREATENEWTABLE, OnDataCreatenewtable)
 
ON_COMMAND(ID_DATA_EMPTYALLDATA, OnDataEmptyalldata)
 
ON_COMMAND(ID_DATA_DATAOPTIMIZATION, OnDataDataoptimization)
 
ON_COMMAND(ID_DATA_SEARCHDATAIN, OnDataSearchdatain)
 
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
 
// CLeftView construction/destruction
 
CLeftView::CLeftView()
 
{
 
// TODO: add construction code here
 
}
 
CLeftView::~CLeftView()
 
{
 
}
 
BOOL CLeftView::PreCreateWindow(CREATESTRUCT& cs)
 
{
 
// TODO: Modify the Window class or styles here by modifying
 
// the CREATESTRUCT cs
 
return CTreeView::PreCreateWindow(cs);
 
}
 
/////////////////////////////////////////////////////////////////////////////
 
// CLeftView drawing
 
void CLeftView::OnDraw(CDC* pDC)
 
{
 
CMysqloneDoc* pDoc = GetDocument();
 
ASSERT_VALID(pDoc);
 
// TODO: add draw code for native data here
 
}
 
void CLeftView::OnInitialUpdate()
 
{
 
CTreeView::OnInitialUpdate();
 
//FillTree();
 
m_TreeImages.Create(IDB_BITMAP1, 16, 1, RGB(255, 255, 255));
 
}
 
/////////////////////////////////////////////////////////////////////////////
 
// CLeftView diagnostics
 
#ifdef _DEBUG
 
void CLeftView::AssertValid() const
 
{
 
CTreeView::AssertValid();
 
}
 
void CLeftView::Dump(CDumpContext& dc) const
 
{
 
CTreeView::Dump(dc);
 
}
 
CMysqloneDoc* CLeftView::GetDocument() // non-debug version is inline
 
{
 
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMysqloneDoc)));
 
return (CMysqloneDoc*)m_pDocument;
 
}
 
#endif //_DEBUG
 
/////////////////////////////////////////////////////////////////////////////
 
// CLeftView message handlers
 
void CLeftView::FillTree()
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
m_tree.DeleteAllItems();
 
m_tree.SetImageList(&m_TreeImages, TVSIL_NORMAL);
 
HTREEITEM hRoot;
 
CMysqloneDoc* pDoc = GetDocument();
 
for (int i = 0; i < pDoc->m_available_bases.GetSize(); i++)
 
{
 
hRoot = m_tree.InsertItem(pDoc->m_available_bases[i], 0, 1);
 
}
 
}
 
void CLeftView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
 
{
 
// TODO: Add your specialized code here and/or call the base class
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
CMysqloneDoc* pDoc = GetDocument();
 
if (!pDoc->connected) {
 
m_tree.DeleteAllItems();
 
return;
 
}
 
FillTree();
 
}
 
void CLeftView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
 
{
 
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
CMysqloneDoc* pDoc = GetDocument();
 
if (!pDoc->connected) {return;}
 
pDoc->current_table = "";
 
HTREEITEM nodSelected = m_tree.GetSelectedItem();
 
if (nodSelected>=0) {
 
CString strSelected=m_tree.GetItemText(nodSelected);
 
GetDocument()->SetTitle(strSelected);
 
}
 
HTREEITEM parent;
 
parent = m_tree.GetParentItem (nodSelected);
 
if (parent) {
 
pDoc->current_table = m_tree.GetItemText (nodSelected);
 
pDoc->UpdateAllViews (this);
 
return;
 
}
 
HTREEITEM child;
 
while (child = m_tree.GetChildItem (nodSelected)) {
 
m_tree.DeleteItem (child);
 
}
 
CString base_name = m_tree.GetItemText (nodSelected);
 
pDoc->current_base = base_name;
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
MYSQL_RES * my_res;
 
MYSQL_ROW row;
 
CString sql;
 
mysql_select_db (mysql, base_name.GetBuffer(255));
 
if (mysql_query (mysql, "SHOW TABLES")) {
 
AfxMessageBox ("Query SHOW databases failed");
 
return;
 
}
 
my_res = mysql_store_result(mysql);
 
while (row = mysql_fetch_row (my_res)) {
 
char buffer[255];
 
strcpy (buffer, row[0]);
 
m_tree.InsertItem (_T(buffer), nodSelected);
 
}
 
mysql_free_result (my_res);
 
*pResult = 0;
 
}
 
void CLeftView::OnNewDatabase()
 
{
 
CNewDatabase dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.InsertItem(dlg.m_newdatabase, TVI_ROOT);
 
m_tree.SelectItem(hitem);
 
}
 
}
 
void CLeftView::OnDataDropdatabase()
 
{
 
CDeleteDatabaseDlg dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
CString selected=m_tree.GetItemText(hitem);
 
m_tree.DeleteItem(hitem);
 
}
 
}
 
void CLeftView::OnNewTable()
 
{
 
CCreateNewTableDlg dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
HTREEITEM childitem=m_tree.GetChildItem(hitem);
 
// childitem = m_tree.InsertItem(dlg.m_newtable, TVI_FIRST);
 
m_tree.SelectItem(childitem);
 
}
 
}
 
void CLeftView::OnMysqlQuery()
 
{
 
CSqlQueryDlg dlg;
 
if (dlg.DoModal() == IDOK ){
 
dlg.OnOK();
 
}
 
}
 
void CLeftView::OnDataSeelastsqlquery()
 
{
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
const char* last_query;
 
CString noresult;
 
CString temp;
 
last_query=mysql_info(mysql);
 
temp=(CString)last_query;
 
if (temp=="NULL") {
 
noresult="No any SQL request was done till now";
 
AfxMessageBox(noresult,MB_ICONINFORMATION);
 
}
 
else {
 
AfxMessageBox(temp,MB_ICONINFORMATION);
 
}
 
}
 
void CLeftView::OnDataCreatenewtable()
 
{
 
CCreateNewTableDlg dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
HTREEITEM childitem=m_tree.GetChildItem(hitem);
 
// childitem = m_tree.InsertItem(dlg.m_newtable, TVI_FIRST);
 
m_tree.SelectItem(childitem);
 
}
 
}
 
void CLeftView::OnDataEmptyalldata()
 
{
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
CString sql="DELETE FROM ";
 
HTREEITEM nodSelected = m_tree.GetSelectedItem();
 
if (nodSelected>=0) {
 
CString strSelected=m_tree.GetItemText(nodSelected);
 
sql +=strSelected;
 
AfxMessageBox("Are you sure to wish to delete ALL data from "+ strSelected,MB_OKCANCEL|MB_ICONQUESTION );
 
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (sql);
 
m_tree.DeleteItem(nodSelected);
 
}
 
}
 
void CLeftView::OnDataDataoptimization()
 
{
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
HTREEITEM childitem=m_tree.GetChildItem(hitem);
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
CMysqloneDoc* pDoc = GetDocument();
 
CString base_name=m_tree.GetItemText(hitem);
 
CString strSelected=m_tree.GetItemText(childitem);
 
pDoc->current_base=base_name;
 
CString sql="OPTIMIZE TABLE ";
 
mysql_select_db(mysql,base_name.GetBuffer(255));
 
sql+=strSelected;
 
((CMysqloneApp*)AfxGetApp())->ExecuteSQL (sql);
 
pDoc->UpdateAllViews (NULL);
 
}
 
void CLeftView::OnDataSearchdatain()
 
{
 
CMysqloneDoc* pDoc = GetDocument();
 
pDoc->current_table = "";
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
MYSQL_RES * my_res;
 
MYSQL_ROW row;
 
CTreeCtrl & m_tree = GetTreeCtrl();
 
HTREEITEM hitem = m_tree.GetSelectedItem();
 
HTREEITEM childitem=m_tree.GetChildItem(hitem);
 
CString base_name=m_tree.GetItemText(hitem);
 
CString strSelected=m_tree.GetItemText(childitem);
 
pDoc->current_base=base_name;
 
CString sql="SELECT * FROM ";
 
sql+=base_name;
 
mysql_select_db (mysql, base_name.GetBuffer(255));
 
if (mysql_query (mysql, sql)) {
 
CString error=mysql_error(mysql);
 
AfxMessageBox (error);
 
return;
 
}
 
my_res = mysql_store_result(mysql);
 
}
 
#if !defined(AFX_LOGINDLG_H__58E63196_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_)
 
#define AFX_LOGINDLG_H__58E63196_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_
 
#if _MSC_VER > 1000
 
#pragma once
 
#endif // _MSC_VER > 1000
 
// LoginDlg.h : header file
 
//
 
/////////////////////////////////////////////////////////////////////////////
 
// CLoginDlg dialog
 
class CLoginDlg : public CDialog
 
{
 
// Construction
 
public:
 
CLoginDlg(CWnd* pParent = NULL); // standard constructor
 
// Dialog Data
 
//{{AFX_DATA(CLoginDlg)
 
enum { IDD = IDD_LOGINDLG };
 
CString m_login;
 
CString m_password;
 
CString m_host;
 
//}}AFX_DATA
 
// Overrides
 
// ClassWizard generated virtual function overrides
 
//{{AFX_VIRTUAL(CLoginDlg)
 
protected:
 
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
 
//}}AFX_VIRTUAL
 
// Implementation
 
protected:
 
// Generated message map functions
 
//{{AFX_MSG(CLoginDlg)
 
// NOTE: the ClassWizard will add member functions here
 
//}}AFX_MSG
 
DECLARE_MESSAGE_MAP()
 
public:
 
afx_msg void OnBnClickedLogin();
 
};
 
//{{AFX_INSERT_LOCATION}}
 
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
 
#endif // !defined(AFX_LOGINDLG_H__58E63196_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_)
 
// LoginDlg.cpp : implementation file
 
//
 
#include "stdafx.h"
 
#include "mysqlone.h"
 
#include "LoginDlg.h"
 
#include ".\logindlg.h"
 
#ifdef _DEBUG
 
#define new DEBUG_NEW
 
#undef THIS_FILE
 
static char THIS_FILE[] = __FILE__;
 
#endif
 
/////////////////////////////////////////////////////////////////////////////
 
// CLoginDlg dialog
 
CLoginDlg::CLoginDlg(CWnd* pParent /*=NULL*/)
 
: CDialog(CLoginDlg::IDD, pParent)
 
{
 
//{{AFX_DATA_INIT(CLoginDlg)
 
m_login = _T("");
 
m_password = _T("");
 
m_host = _T("");
 
//}}AFX_DATA_INIT
 
}
 
void CLoginDlg::DoDataExchange(CDataExchange* pDX)
 
{
 
CDialog::DoDataExchange(pDX);
 
//{{AFX_DATA_MAP(CLoginDlg)
 
DDX_Text(pDX, IDC_EDIT1, m_login);
 
DDX_Text(pDX, IDC_EDIT2, m_password);
 
DDX_Text(pDX, IDC_EDIT3, m_host);
 
//}}AFX_DATA_MAP
 
}
 
BEGIN_MESSAGE_MAP(CLoginDlg, CDialog)
 
//{{AFX_MSG_MAP(CLoginDlg)
 
// NOTE: the ClassWizard will add message map macros here
 
//}}AFX_MSG_MAP
 
ON_BN_CLICKED(IDC_LOGIN, OnBnClickedLogin)
 
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
 
// CLoginDlg message handlers
 
void CLoginDlg::OnBnClickedLogin()
 
{
 
UpdateData();
 
char login[35];
 
char password[25];
 
char host[255];
 
FILE *file;
 
bool valid_login = false;
 
if( m_login =="")
 
{
 
AfxMessageBox("You must provide a username and password or click Cancel!");
 
return;
 
}
 
if( m_password =="")
 
{
 
AfxMessageBox("Invalid login entered");
 
return;
 
}
 
if( m_host =="")
 
{
 
AfxMessageBox("Enter host name, please");
 
return;
 
}
 
try {
 
file = fopen("database.lgn", "r");
 
while( !feof(file) )
 
{
 
fscanf(file, "%s", login);
 
if( strcmp((LPCTSTR)m_login, login) == 0 )
 
{
 
fscanf(file, "%s", password);
 
if( strcmp((LPCTSTR)m_password, password) == 0 )
 
{
 
valid_login = true;
 
}
 
else
 
valid_login = false;
 
}
 
}
 
if( valid_login == true )
 
OnOK();
 
else
 
{
 
AfxMessageBox("Invalid entry data entered! Please try again");
 
}
 
fclose(file);
 
}
 
catch(...)
 
{
 
AfxMessageBox("Could not validate entered information to connect with MySQL database");
 
}
 
UpdateData(FALSE);
 
}
 
// MainFrm.h : interface of the CMainFrame class
 
//
 
/////////////////////////////////////////////////////////////////////////////
 
#if !defined(AFX_MAINFRM_H__58E63188_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_)
 
#define AFX_MAINFRM_H__58E63188_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_
 
#if _MSC_VER > 1000
 
#pragma once
 
class CLeftView;
 
#endif // _MSC_VER > 1000
 
class CMysqloneView;
 
class CMainFrame : public CFrameWnd
 
{
 
protected: // create from serialization only
 
CMainFrame();
 
DECLARE_DYNCREATE(CMainFrame)
 
// Attributes
 
protected:
 
CSplitterWnd m_wndSplitter;
 
public:
 
// Operations
 
public:
 
CStatusBar m_wndStatusBar;
 
CToolBar m_wndToolBar;
 
CReBar m_rebar;
 
CDialogBar m_wndDlgBar;
 
// Overrides
 
// ClassWizard generated virtual function overrides
 
//{{AFX_VIRTUAL(CMainFrame)
 
public:
 
virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
 
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
 
//}}AFX_VIRTUAL
 
// Implementation
 
public:
 
virtual ~CMainFrame();
 
CMysqloneView* GetRightPane();
 
#ifdef _DEBUG
 
virtual void AssertValid() const;
 
virtual void Dump(CDumpContext& dc) const;
 
#endif
 
protected: // control bar embedded members
 
// Generated message map functions
 
protected:
 
//{{AFX_MSG(CMainFrame)
 
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
 
//}}AFX_MSG
 
afx_msg void OnUpdateViewStyles(CCmdUI* pCmdUI);
 
afx_msg void OnViewStyle(UINT nCommandID);
 
DECLARE_MESSAGE_MAP()
 
public:
 
afx_msg void OnHelpGotomysqlsite();
 
afx_msg void OnNewConnection();
 
afx_msg void OnCloseConnection();
 
afx_msg void OnHelpMysqlinfo();
 
};
 
/////////////////////////////////////////////////////////////////////////////
 
//{{AFX_INSERT_LOCATION}}
 
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
 
#endif // !defined(AFX_MAINFRM_H__58E63188_DD0B_11D9_A8EF_BCC8AEF81D60__INCLUDED_)
 
// MainFrm.cpp : implementation of the CMainFrame class
 
//
 
#include "stdafx.h"
 
#include "mysqlone.h"
 
#include "MainFrm.h"
 
#include "LeftView.h"
 
#include "mysqloneView.h"
 
#include "SqlQueryDlg.h"
 
#include "NewDatabase.h"
 
#include "MySQLInfoDlg.h"
 
#include ".\mainfrm.h"
 
#include "mysqlonedoc.h"
 
#ifdef _DEBUG
 
#define new DEBUG_NEW
 
#undef THIS_FILE
 
static char THIS_FILE[] = __FILE__;
 
#endif
 
/////////////////////////////////////////////////////////////////////////////
 
// CMainFrame
 
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
 
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
 
//{{AFX_MSG_MAP(CMainFrame)
 
ON_WM_CREATE()
 
ON_COMMAND(ID_NEW_CONNECTION, OnNewConnection)
 
ON_COMMAND(ID_CLOSE_CONNECTION, OnCloseConnection)
 
ON_COMMAND(ID_HELP_GOTOMYSQLSITE, OnHelpGotomysqlsite)
 
//}}AFX_MSG_MAP
 
ON_UPDATE_COMMAND_UI_RANGE(AFX_ID_VIEW_MINIMUM, AFX_ID_VIEW_MAXIMUM, OnUpdateViewStyles)
 
ON_COMMAND_RANGE(AFX_ID_VIEW_MINIMUM, AFX_ID_VIEW_MAXIMUM, OnViewStyle)
 
ON_COMMAND(ID_HELP_MYSQLINFO, OnHelpMysqlinfo)
 
END_MESSAGE_MAP()
 
static UINT indicators[] =
 
{
 
ID_SEPARATOR, // status line indicator
 
ID_INDICATOR_CAPS,
 
ID_INDICATOR_NUM,
 
ID_INDICATOR_SCRL,
 
};
 
/////////////////////////////////////////////////////////////////////////////
 
// CMainFrame construction/destruction
 
CMainFrame::CMainFrame()
 
{
 
// TODO: add member initialization code here
 
}
 
CMainFrame::~CMainFrame()
 
{
 
}
 
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
 
{
 
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
 
return -1;
 
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
 
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
 
!m_wndToolBar.LoadToolBar(IDR_TOOLBAR2))
 
{
 
TRACE0("Failed to create toolbar\n");
 
return -1; // fail to create
 
}
 
if (!m_wndStatusBar.Create(this) ||
 
!m_wndStatusBar.SetIndicators(indicators,
 
sizeof(indicators)/sizeof(UINT)))
 
{
 
TRACE0("Failed to create status bar\n");
 
return -1; // fail to create
 
}
 
// TODO: Delete these three lines if you don't want the toolbar to be dockable
 
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
 
EnableDocking(CBRS_ALIGN_ANY);
 
DockControlBar(&m_wndToolBar);
 
return 0;
 
}
 
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
 
CCreateContext* pContext)
 
{
 
// create splitter window
 
if (!m_wndSplitter.CreateStatic(this, 1, 2))
 
return FALSE;
 
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView), CSize(200, 100), pContext) ||
 
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CMysqloneView), CSize(100, 100), pContext))
 
{
 
m_wndSplitter.DestroyWindow();
 
return FALSE;
 
}
 
return TRUE;
 
}
 
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
 
{
 
if( !CFrameWnd::PreCreateWindow(cs) )
 
return FALSE;
 
// TODO: Modify the Window class or styles here by modifying
 
// the CREATESTRUCT cs
 
return TRUE;
 
}
 
/////////////////////////////////////////////////////////////////////////////
 
// CMainFrame diagnostics
 
#ifdef _DEBUG
 
void CMainFrame::AssertValid() const
 
{
 
CFrameWnd::AssertValid();
 
}
 
void CMainFrame::Dump(CDumpContext& dc) const
 
{
 
CFrameWnd::Dump(dc);
 
}
 
#endif //_DEBUG
 
/////////////////////////////////////////////////////////////////////////////
 
// CMainFrame message handlers
 
CMysqloneView* CMainFrame::GetRightPane()
 
{
 
CWnd* pWnd = m_wndSplitter.GetPane(0, 1);
 
CMysqloneView* pView = DYNAMIC_DOWNCAST(CMysqloneView, pWnd);
 
return pView;
 
}
 
void CMainFrame::OnUpdateViewStyles(CCmdUI* pCmdUI)
 
{
 
// TODO: customize or extend this code to handle choices on the
 
// View menu.
 
CMysqloneView* pView = GetRightPane();
 
// if the right-hand pane hasn't been created or isn't a view,
 
// disable commands in our range
 
if (pView == NULL)
 
pCmdUI->Enable(FALSE);
 
else
 
{
 
DWORD dwStyle = pView->GetStyle() & LVS_TYPEMASK;
 
// if the command is ID_VIEW_LINEUP, only enable command
 
// when we're in LVS_ICON or LVS_SMALLICON mode
 
if (pCmdUI->m_nID == ID_VIEW_LINEUP)
 
{
 
if (dwStyle == LVS_ICON || dwStyle == LVS_SMALLICON)
 
pCmdUI->Enable();
 
else
 
pCmdUI->Enable(FALSE);
 
}
 
else
 
{
 
// otherwise, use dots to reflect the style of the view
 
pCmdUI->Enable();
 
BOOL bChecked = FALSE;
 
switch (pCmdUI->m_nID)
 
{
 
case ID_VIEW_DETAILS:
 
bChecked = (dwStyle == LVS_REPORT);
 
break;
 
case ID_VIEW_SMALLICON:
 
bChecked = (dwStyle == LVS_SMALLICON);
 
break;
 
case ID_VIEW_LARGEICON:
 
bChecked = (dwStyle == LVS_ICON);
 
break;
 
case ID_VIEW_LIST:
 
bChecked = (dwStyle == LVS_LIST);
 
break;
 
default:
 
bChecked = FALSE;
 
break;
 
}
 
pCmdUI->SetRadio(bChecked ? 1 : 0);
 
}
 
}
 
}
 
void CMainFrame::OnViewStyle(UINT nCommandID)
 
{
 
// TODO: customize or extend this code to handle choices on the
 
// View menu.
 
CMysqloneView* pView = GetRightPane();
 
// if the right-hand pane has been created and is a CMysqloneView,
 
// process the menu commands...
 
if (pView != NULL)
 
{
 
DWORD dwStyle = -1;
 
switch (nCommandID)
 
{
 
case ID_VIEW_LINEUP:
 
{
 
// ask the list control to snap to grid
 
CListCtrl& refListCtrl = pView->GetListCtrl();
 
refListCtrl.Arrange(LVA_SNAPTOGRID);
 
}
 
break;
 
// other commands change the style on the list control
 
case ID_VIEW_DETAILS:
 
dwStyle = LVS_REPORT;
 
break;
 
case ID_VIEW_SMALLICON:
 
dwStyle = LVS_SMALLICON;
 
break;
 
case ID_VIEW_LARGEICON:
 
dwStyle = LVS_ICON;
 
break;
 
case ID_VIEW_LIST:
 
dwStyle = LVS_LIST;
 
break;
 
}
 
// change the style; window will repaint automatically
 
if (dwStyle != -1)
 
pView->ModifyStyle(LVS_TYPEMASK, dwStyle);
 
}
 
}
 
void CMainFrame::OnNewConnection()
 
{
 
MYSQL* mysql = &(((CMysqloneApp*)AfxGetApp())->mysql);
 
CMysqloneApp* MyApp=((CMysqloneApp*)AfxGetApp());
 
MyApp->ConnectToDb();
 
CMysqloneDoc* pDoc=(CMysqloneDoc*)GetActiveDocument();
 
pDoc->connected = true;
 
pDoc->UpdateAllViews (NULL);
 
}
 
void CMainFrame::OnCloseConnection()
 
{
 
CMysqloneApp* MyApp=((CMysqloneApp*)AfxGetApp());
 
MyApp->CloseConnectionDb();
 
CMysqloneDoc* pDoc=(CMysqloneDoc*)GetActiveDocument();
 
pDoc->connected = false;
 
pDoc->UpdateAllViews(NULL);
 
}
 
void CMainFrame::OnHelpGotomysqlsite()
 
{
 
ShellExecute(NULL,"open", "http://www.mysql.com", "", "c:\\", SW_SHOWNORMAL);
 
}
 
void CMainFrame::OnHelpMysqlinfo()
 
{
 
CMySQLInfoDlg dlg;
 
if (dlg.DoModal() == IDOK )
 
{
 
dlg.OnBnClickedExit();
 
}
 
}
 
// mysqlone.h : main header file for the MYSQLONE application
 
//
 
#if !defined(AFX_MYSQLONE_H__58E63184_DD0B_11D9_A8EF_


Всего комментариев: 2


aocidozepeye

eserpsop@salkjf.sdgmaipop.com

Applying csp.ysni.aurov.com.uok.rq intrasellar twice-daily [URL=http://albfoundation.org/cenforce/ - cheapest cenforce[/URL - [URL=http://graphicatx.com/item/fosamax/ - alternativas a fosamax[/URL - [URL=http://weblabhn.com/product/vidalista/ - vidalista[/URL - [URL=http://saunasavvy.com/item/avapro/ - avapro[/URL - [URL=http://elearning101.org/item/wellbutrin/ - buying wellbutrin online safely[/URL - [URL=http://a1sewcraft.com/xenical/ - orlistat[/URL - [URL=http://poodlebreederlist.com/ketasma/ - ketasma in sydney[/URL - [URL=http://staffordshirebullterrierhq.com/item/caverta/ - caverta tadafil 50[/URL - [URL=http://healthycrickets.com/item/lanoxin/ - buy lanoxin in usa online[/URL - [URL=http://johncavaletto.org/item/verampil/ - low dose verampil[/URL - [URL=http://thesteki.com/celebrex/ - central serous retinopathy and celebrex[/URL - [URL=http://ma-roots.org/item/atarax/ - atarax pills without prescription[/URL - [URL=http://elearning101.org/item/benicar/ - benicar[/URL - [URL=http://travelhockeyplanner.com/item/etibest-md/ - etibest md[/URL - [URL=http://fontanellabenevento.com/selsun/ - generic selsun from canada online[/URL - two-way cenforce alternativa fosamax canadian vidalista avapro online rezept wellbutrin online pharamacy orlistat online ketasma canadian pharmacy overnight shipping caverta generic lanoxin fda verampil apotheke kaufen celebrex drug prescription atarax online american benicar online cheap us cheap etibest md selsun artist, http://albfoundation.org/cenforce/ cenforce for sale http://graphicatx.com/item/fosamax/ fosamax rhodos http://weblabhn.com/product/vidalista/ vidalista online no script http://saunasavvy.com/item/avapro/ avapro shopping acheter avapro canada http://elearning101.org/item/wellbutrin/ board wellbutrin http://a1sewcraft.com/xenical/ xenical http://poodlebreederlist.com/ketasma/ ketasma 1 preco http://staffordshirebullterrierhq.com/item/caverta/ caverta online ohio http://healthycrickets.com/item/lanoxin/ lanoxin overnight delivery http://johncavaletto.org/item/verampil/ verampil a vendre montreal http://thesteki.com/celebrex/ purchase celebrex http://ma-roots.org/item/atarax/ online store atarax http://elearning101.org/item/benicar/ generic benicar price comparison http://travelhockeyplanner.com/item/etibest-md/ etibest md en europe http://fontanellabenevento.com/selsun/ selsun delivered next day clustering hormone-resistant immerse extremis.

2021-01-28 12:35:09


efopapapu

owirose@sdfs.sdgmaipop.com

May jdy.wrmz.aurov.com.lih.hm known, [URL=http://elearning101.org/item/diclofenac/ - diclofenac[/URL - [URL=http://jacksfarmradio.com/product/zithromax/ - zithromax coupons[/URL - [URL=http://graphicatx.com/item/ed-advanced-pack/ - pay shipping for ed advanced pack[/URL - [URL=http://scoverage.org/order-plaquenil/ - plaquenil generic pills[/URL - plaquenil generic pills [URL=http://wow-70.com/item/renova/ - acheter renova generique canada[/URL - buy cheap renova canada [URL=http://advantagecarpetca.com/pregnyl/ - online pregnyl us[/URL - [URL=http://a1sewcraft.com/canadian-pharmacy-cialis/ - canadian pharmacy online no script[/URL - [URL=http://talleysbooks.com/buy-levitra/ - buy levitra[/URL - [URL=http://stillwateratoz.com/brand-levitra/ - generalt order brand levitra[/URL - [URL=http://poodlebreederlist.com/garcinia-cambogia/ - garcinia cambogia[/URL - [URL=http://staffordshirebullterrierhq.com/item/compazine/ - compazine paid with paypal[/URL - [URL=http://damcf.org/item/cialis-black/ - purchase cialis black[/URL - cialis black from india [URL=http://columbiainnastoria.com/viagra-com/ - discount viagra[/URL - [URL=http://allgeekguide.com/item/diprovate-g-plus/ - diprovate g plus generico online espana[/URL - diprovate g plus [URL=http://healthycrickets.com/item/galvus/ - cheap galvus quick shipment us[/URL - iron diclofenac vendita on line in italia buy zithromax online ed advanced pack online without prescription lowest plaquenil prices canadaian renova pregnyl sin receta en farmacias generic cialis canada pharmacy online levitra brand-levitra online fda safe way to order garcinia cambogia best price generic compazine online prescription buy cialis black without prescription viagra.com canadian diprovate-g-plus costs cheapest galvus overnight shipping medius, rating palsy; http://elearning101.org/item/diclofenac/ diclofenac http://jacksfarmradio.com/product/zithromax/ buy zithromax online zithromax without a doctor http://graphicatx.com/item/ed-advanced-pack/ buyimg ed advanced pack in australia http://scoverage.org/order-plaquenil/ canadian pharmacy plaquenil http://wow-70.com/item/renova/ acheter renova generique canada http://advantagecarpetca.com/pregnyl/ online pregnyl us http://a1sewcraft.com/canadian-pharmacy-cialis/ buy cialis online pharmacy http://talleysbooks.com/buy-levitra/ vardenafil 20 mg http://stillwateratoz.com/brand-levitra/ generic brand levitra online us http://poodlebreederlist.com/garcinia-cambogia/ find the cheapest garcinia cambogia for sale http://staffordshirebullterrierhq.com/item/compazine/ purchase compazine no prescription http://damcf.org/item/cialis-black/ cialis black without dr prescription http://columbiainnastoria.com/viagra-com/ viagra http://allgeekguide.com/item/diprovate-g-plus/ diprovate-g-plus in 3 days http://healthycrickets.com/item/galvus/ no prescription galvus canada online droops microthrombi.

2021-01-28 12:35:08


Новый комментарий:
























Яндекс.Метрика