[Winapi] + sqlite - podstawy

0

Kod w wersji konsolowej wygląda tak:

#include "sqlite3.h"
#include "libsqlitewrapped.h"

using namespace std;

int main()
{
	char i;
	int k=1;
	Database db("tutorial.db");
	if (!db.Connected())
	{
		printf("Database not connected - exiting\n");
		exit(-1);
	}
	Query q(db);
	char cos[1000];
	string cos2="player";
	sprintf(cos, "select name from %s where num=%i", cos2,k);

	string name = q.get_string(cos);
	long num = q.get_count("select num from player where name='Grymse'");
	printf("The name of player#1 is '%s'\n", name.c_str());
	printf("The number of 'Grymse' is %ld\n", num);
	scanf("%i",&i);
}

Wszystko działa jak należy. Postanowiłem zatem przejść do Winapi. Na podstawie tego, co udało mi się przeczytać, skleiłem coś takiego:

#include <windows.h>
#include "sqlite3.h"
#include "libsqlitewrapped.h"

using namespace std;
int button[100];
char a[200]; 
HWND wnd_crt[10];
static TCHAR lpszAppName[] = TEXT( "API Windows" );

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
int xPos;
char ss[201]; 

case WM_CREATE: 
{
	wnd_crt[0]=CreateWindow("STATIC"," dowolny tekst ", WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 200, 20, hWnd, (HMENU)100, GetModuleHandle(NULL), NULL);
	wnd_crt[1]=CreateWindow("STATIC"," dowolny tekst ", WS_CHILD | WS_VISIBLE, 10, 40, 200, 20, hWnd, (HMENU)101, GetModuleHandle(NULL), NULL);  
	wnd_crt[3]=CreateWindow("EDIT","", WS_CHILD | WS_VISIBLE |WS_BORDER, 10, 70, 200, 20, hWnd, (HMENU)103, GetModuleHandle(NULL), NULL);    
	wnd_crt[7]=CreateWindow("BUTTON","z bazy  ", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 10, 100, 200, 30, hWnd, (HMENU)107, GetModuleHandle(NULL), NULL);  
	wnd_crt[9]=CreateWindow("BUTTON","message  ", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 10, 200, 200, 30, hWnd, (HMENU)108, GetModuleHandle(NULL), NULL);
	wnd_crt[8]=CreateWindow("EDIT","", WS_CHILD | WS_VISIBLE | ES_READONLY | WS_BORDER, 10, 130, 200, 20, hWnd, (HMENU)104, GetModuleHandle(NULL), NULL);
}

case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case 107:
{
	int k=1;
	int j=0;
	Database db("tutorial.db");
	if (!db.Connected())
	{
		j=-1;
		
	}
	Query q(db);
	char cos[1000];
	char cos3[1000];
	string cos2="player";
	sprintf(cos, "select name from %s where num=%i", cos2,k);
	j=400;
	string name = q.get_string(cos);
	sprintf(cos3,"w: %s w2: %i ",name,j);
	wnd_crt[8]=CreateWindow("EDIT",cos3, WS_CHILD | WS_VISIBLE | ES_READONLY |WS_BORDER, 10, 130, 200, 20, hWnd, (HMENU)104, GetModuleHandle(NULL), NULL);
}
break;
case 108:
{	
	GetWindowText(wnd_crt[3],ss,200);
    MessageBox(NULL, ss,"Info", MB_OK); 
}
break;
}   
}
break;
case WM_DESTROY: PostQuitMessage(0); break;
case WM_KEYDOWN: break;
default: return (DefWindowProc(hWnd, uMsg, wParam, lParam));
}
return(0L);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ 
MSG msg;
WNDCLASS wndclass;
HWND hWnd; 
wndclass.style = CS_HREDRAW | CS_VREDRAW; 
wndclass.lpfnWndProc = MainWndProc; 
wndclass.cbClsExtra = 0; 
wndclass.cbWndExtra = 0; 
wndclass.hInstance = hInstance; 
wndclass.hIcon = NULL; 
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
wndclass.lpszMenuName = NULL; 
wndclass.lpszClassName = lpszAppName; 

if(RegisterClass(&wndclass) == 0) 

return FALSE; 

hWnd = CreateWindow(lpszAppName, lpszAppName, 
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if(hWnd == NULL)
return FALSE;


ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);

while(GetMessage(&msg, NULL, 0, 0))
{
      TranslateMessage(&msg);
      DispatchMessage(&msg);
}

return msg.wParam;
} 

Jest tam trochę śmieci, ale z tym zrobi się porządek. Problemem jest "case 107:". Przerzuciłem instrukcje łączenia z bazą - nie wiem, czy to dobre miejsce - może lepiej przed "switch (uMsg)" - choć wtedy łączenie się z bazą będzie następować przy każdym zdarzeniu, ale globalnie nie działa (błędy).

	string name = q.get_string(cos);
	sprintf(cos3,"w: %s w2: %i ",name,j);

Powyższy fragment nie do końca działa. W oknie programu pojawia się "w: (null) w2: -858993460". Trochę to dziwne, gdyż parę linii wcześniej mamy "j=400". Wynik selecta także jest dziwny - baza w końcu istnieje, nie była modyfikowana, znajduje się we właściwym katalogu. Dla tej samej bazy, wcześniejszy program w wersji konsolowej, działa bez zarzutu.


Posiedziałem przy tym jeszcze:

string cos2="player";
sprintf(cos3,"--%s",cos2);

W programie, w polu tekstowym, po kliknięciu na przycisk (wcześniej pole jest puste), mamy "--(null)". :|

0

Wszystkie printf'y to funkcje języka C. Format "%s" to łańcuch w stylu C, czyli tablica znaków zakończona zerem. Czyli

string cos2="player";
sprintf(cos3,"--%s",cos2.c_str());
//powyższe 'cos3' musi być tablicą char !

W C++ używa się dużo bezpieczniejszych strumieni:

//analogicznie do tego:
//sprintf(cos3,"w: %s w2: %i ",name,j);
ostringstream ssout;
ssout << "w: " << name << " w2: " << j << " ";
string cos3 = ssout.str();

//...

istringstream ssin;
ssin.str("1 2 3");
ssin >> i >> j >> k;
0

cos3 musi być tablicą, bo ta struktura jest przekazywana do pola tekstowego.

char cos3[1000];
ostringstream ssout;
ssout << "w: " << name << " w2: " << j << " ";
cos3 = ssout.str();

Niestety efekt jest taki:

e:\bd\test3\test3\test3.cpp(64) : error C2440: '=' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'char [1000]'
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Ax=std::allocator<char>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called


Już sobie poradziłem - zamiast:

        cos3 = ssout.str();

trzeba było zrobić:

        string abc=ssout.str();
	int lng=abc.length();
	int y;
	for(y=0;y<lng;y++)
	{
		cos3[y]=abc[y];
	}
	for(y=lng;y<100;y++)
	{
		cos3[y]=' ';
	}
0
string cos3 = ssout.str();
CreateWindowA("EDIT",cos3.c_str(), ...
0

Działa, thnx.
Zrobiłem usuwanie wiersza z tabeli. Problem w tym, że aby zobaczyć efekt, muszę jeszcze raz uruchomić tworzony program, mimo, że wywołuję funkcję, która za każdym razem na nowo wypisuje mi zawartość tabeli (kilka funkcji, podobnych do case123, różnią się jedynie stringiem na początku, który oznacza nazwę tabeli):

//************zmienne globalne***
string tabela;
HWND wnd_crt[200];
int cos7=0;

//************zmienne lokalne***
	string func;
	string kawalek;
	string linia;
	string numer;
	ostringstream instrukcja;
	ostringstream wynik;
//****************************
case 123:
{
	tabela="bluetooth";
	MessageBox(NULL, tabela.c_str(),"Info", MB_OK);
	instrukcja.str("");
	instrukcja<< "select * from " << tabela;
	func=instrukcja.str();
	q.get_result(func);
	wynik.str("");

	while (q.fetch_row())
	{
		kawalek=q.getstr();
		wynik<<kawalek<<".  ";
		kawalek=q.getstr();
		wynik<<kawalek<<"  ";
		kawalek=q.getstr();
		wynik<<kawalek<<"  ";
		kawalek=q.getstr();
		wynik<<kawalek<<"  ";
		kawalek=q.getstr();
		wynik<<kawalek<<"  ";
		linia=wynik.str();
		SendMessage(wnd_crt[100], CB_ADDSTRING, 0, (LPARAM)linia.c_str());
		wynik.str("");
	}
	q.free_result();
	wnd_crt[100]=CreateWindowEx(WS_EX_CLIENTEDGE, "COMBOBOX", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | CBS_DROPDOWN, 150, 50, 250, 200, hWnd, NULL, GetModuleHandle(NULL), NULL);
}
break;

case 129:
{
	int index = SendMessage(wnd_crt[100], CB_GETCURSEL, 0, 0);
	//SendMessage(wnd_crt[100], CB_GETLBTEXT, index, cos7);
	instrukcja.str("");
	instrukcja << "numer:" << index;
	func=instrukcja.str();
	wnd_crt[1]=CreateWindow("STATIC",func.c_str(), WS_CHILD | WS_VISIBLE, 150, 200, 200, 20, hWnd, (HMENU)101, GetModuleHandle(NULL), NULL);
}
break;

case 127:
{
	GetWindowText(wnd_crt[101],ss,200);
	numer=ss;	
	instrukcja.str("");
	instrukcja << "delete from " << tabela << " where num = "<<numer;
	func=instrukcja.str();
        MessageBox(NULL, func.c_str(),"Info", MB_OK); 
	q.execute(func);
}
break;

Można jakoś łatwo wyczyścić taką listę, żeby na nowo ją stworzyć?
Drugi problem to oczywiście odczyt wybranej opcji z listy (case 129). W sumie wystarczy tylko znajomość indeksu z listy - resztę można sobie pobrać z bazy. Jeśli funkcja zostanie wywołana (czyli nastąpi rozwinięcie listy), niezależnie od tego, czy będzie pusta, czy nie, w polu tekstowym zawsze jest "numer: -1".

1 użytkowników online, w tym zalogowanych: 0, gości: 1