PDA

Visualizza la versione completa : [C++] GUI con Win32 Aiuto


Stormlord1736
06-03-2010, 01:42
Il seguente programma scrive "Prova prova prova prova" in colonna per 50 volte a intervalli di 200ms, però la scroll bar rimane sempre all'inizio, mentre vorrei che andasse giù insieme al testo.

Ad esempio come avviene nelle finestre delle chat tipo msn o skype.

Come dovrei fare? Grazie in anticipo

Ecco il codice:

#include <windows.h>
#include <string>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define Show(Window) RedrawWindow(Window,0,0,0);ShowWindow(Window,SW_SH OW);
using namespace std;

MSG msg;
HINSTANCE hInst;
HWND form1,label21;

int i=0;
char buffer[50];

void procedura_thread();
void reg(UINT style,WNDPROC lpfnWndProc,int cbClsExtra,int cbWndExtra,HINSTANCE hInstance,HICON hIcon,HCURSOR hCursor,HBRUSH hbrBackground,LPCTSTR lpszMenuName,LPCTSTR lpszClassName);

LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
{

hInst = hInstance;
reg(CS_HREDRAW | CS_VREDRAW | CS_OWNDC,WinProc,0,0,hInst,LoadIcon(NULL,IDI_WINLO GO),LoadCursor(NULL,IDC_ARROW),(HBRUSH)(COLOR_BTNF ACE+1),NULL,"principale");

form1 = CreateWindow("principale","Finestra",WS_MINIMIZEBOX | WS_SIZEBOX | WS_CAPTION | WS_MAXIMIZEBOX | WS_POPUP | WS_SYSMENU,600,300,600,440,NULL,(HMENU)NULL,hInst, NULL);
label21 = CreateWindow("Edit","",WS_CHILD | ES_LEFT | WS_BORDER| WS_VSCROLL | WS_HSCROLL | WS_VISIBLE | ES_READONLY | EM_SCROLLCARET | ES_MULTILINE | ES_AUTOVSCROLL,1,1,583,403,form1,(HMENU)NULL,hInst ,NULL);

Show(form1);
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&procedura_thread,NULL,0,NULL);

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

LRESULT CALLBACK WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg==WM_DESTROY)
{
UnregisterClass("principale",hInst);
PostQuitMessage(0);
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}


void procedura_thread()
{
char Text[50];
char buff[5000];
i=0;
while(i<=50)
{
sprintf(Text,"Prova prova prova prova%c%c",0x0D,0x0A);
strncat (buff, Text, 46);
SetWindowText(label21,buff);
Sleep(200);
Show(form1);
i++;
}
}

void reg(UINT style,WNDPROC lpfnWndProc,int cbClsExtra,int cbWndExtra,HINSTANCE hInstance,HICON hIcon,HCURSOR hCursor,HBRUSH hbrBackground,LPCTSTR lpszMenuName,LPCTSTR lpszClassName)
{
WNDCLASS wc;

wc.style = style;
wc.lpfnWndProc = lpfnWndProc;
wc.cbClsExtra = cbClsExtra;
wc.cbWndExtra = cbWndExtra;
wc.hInstance = hInstance;
wc.hIcon = hIcon;
wc.hCursor = hCursor;
wc.hbrBackground = hbrBackground;
wc.lpszMenuName = lpszMenuName;
wc.lpszClassName = lpszClassName;
RegisterClass(&wc);
}

oregon
06-03-2010, 12:12
Io aggiungerei l'header

#include <windowsx.h>

e modificherei questa funzione così



void procedura_thread()
{
char Text[50];
char buff[5000] = {0};
i=0;

while(i<50)
{
sprintf(Text,"%d Prova prova prova prova\r\n", i+1);
strncat (buff, Text, 46);
SetWindowText(label21, buff);
Edit_Scroll(label21, Edit_GetLineCount(label21), 0);
Sleep(200);
Show(form1);
i++;
}
}

Stormlord1736
06-03-2010, 12:56
Ok è perfetto! grazie mille

ora vorrei aggiungere ancora altri due controlli ad esempio:

mentre la scrollbar scende, se la riporto su dovrebbe mostrarmi il testo corrispondente, mentre ora continua a visualizzarmi sempre le ultime righe stampate.

Inoltre vorrei anche fare in modo che se clicco con il mouse su un carattere il cursore deve rimanere fermo su di esso e così anche la scrollbar dovrebbe fermarsi, ad esempio gestirei con un if
Edit_Scroll(label21, Edit_GetLineCount(label21), 0), ma non so come gestire vari eventi(spostamento del cursore su una determinata riga/colonna, oppure come faccio a spostare il cursore ad ogni ristampa?).

Ora invece il cursore a ogni SetWindowText(label21, buff); Ritorna all’inizio dello scritto.

Come potrei fare? Grazie in anticipo.

oregon
06-03-2010, 13:05
Originariamente inviato da Stormlord1736
mentre la scrollbar scende, se la riporto su dovrebbe mostrarmi il testo corrispondente, mentre ora continua a visualizzarmi sempre le ultime righe stampate.

Che vuol dire? Mentre scende significa che il loop è in esecuzione e quindi viene aggiunto la prossima linea all'ultimo e visualizzata ... ovvio che visualizza sempre le ultime righe ... era quello che volevi ...


Inoltre vorrei anche fare in modo che se clicco con il mouse su un carattere il cursore deve rimanere fermo su di esso e così anche la scrollbar dovrebbe fermarsi, ad esempio gestirei con un if ...

Non ho capito quello che vuoi fare ma, se hai un ciclo come quello che hai mostrato, allora dovrai intervenire sul ciclo stesso per fermarlo ...

Stormlord1736
06-03-2010, 13:18
Cerco di spiegare meglio riferendomi magari al comportamento di chat come msn o skype che magari rende meglio l'idea.

Ad esempio su msn quando qualcuno scrive un messaggio la scrollbar scende giù insieme al testo ed è quello che ora il programma fa però, se ad esempio sempre su msn voglio rileggere quello che mi hanno scritto precedentemente allora salgo su con la scrollbar e anche se continuano ad arrivare nuovi messaggi istantanei la scrollbar non scorre più insieme al testo ma rimane ferma a visualizzare i messaggi precedenti.

In poche parole vorrei una finestra che si comporti esattamente come quella di msn, così anche se seleziono del testo oppure posiziono il cursore su una lettera, questi non devono variare o ogni ristampa, spero di essere stato un po più chiaro.

Grazie in anticipo

Stormlord1736
07-03-2010, 18:44
EM_CANUNDO
EM_CHARFROMPOS
EM_EMPTYUNDOBUFFER
EM_FMTLINES
EM_GETCUEBANNER
EM_GETFIRSTVISIBLELINE
EM_GETHANDLE
EM_GETHILITE
EM_GETIMESTATUS
EM_GETLIMITTEXT
EM_GETLINE
EM_GETLINECOUNT
EM_GETMARGINS
EM_GETMODIFY
EM_GETPASSWORDCHAR
EM_GETRECT
EM_GETSEL
EM_GETTHUMB
EM_GETWORDBREAKPROC
EM_HIDEBALLOONTIP
EM_LIMITTEXT
EM_LINEFROMCHAR
EM_LINEINDEX
EM_LINELENGTH
EM_LINESCROLL
EM_NOSETFOCUS
EM_POSFROMCHAR
EM_REPLACESEL
EM_SCROLL
EM_SCROLLCARET
EM_SETCUEBANNER
EM_SETHANDLE
EM_SETHILITE
EM_SETIMESTATUS
EM_SETLIMITTEXT
EM_SETMARGINS
EM_SETMODIFY
EM_SETPASSWORDCHAR
EM_SETREADONLY
EM_SETRECTEM_SETRECT
EM_SETRECTNP
EM_SETSEL
EM_SETTABSTOPS
EM_SETWORDBREAKPROC
EM_SHOWBALLOONTIP
EM_TAKEFOCUS
EM_UNDO
WM_UNDO


Questi sono tutti i messaggi che posso utilizzare per vari controlli sugli edit, ma non sono proprio riuscito a trovare quello che fa per me.

Avrei la necessità di sapere se la scroll bar viene spostata manualmente dell'utente, ho provato quindi con EM_GETTHUMB (non so se sia il messaggio corretto) ma ritorna sempre 0.

Poi ho utilizzato anche EM_GETSEL e EM_SETSEL, per fare in modo che se l'utente seleziona del testo, questo deve rimanere selezionato anche dopo che l'edit viene ristampato con il testo agiuntivo.

Dopo svariati tentativi non sono riuscito ad ottenere nulla.
Il risultato che voglio ottenere è proprio quello di creare un edit che si comporti come una finestra di conversazione di messenger dove i messaggi istantanei sono la stringa "Prova prova prova".

Come posso fare? Grazie in anticipo

Stormlord1736
24-03-2010, 02:57
Alla fine ho risolto con una cosa di questo tipo (in caso dovesse servire a qualcuno):



#include <windows.h>
#include <string>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <algorithm>

using namespace std;

MSG msg;
HINSTANCE hInst;
HWND form1,scroll1,label21;
SCROLLINFO si ;


char buffer[50];
char buff[5000] = {0};
char buf[70][70];
int nLineMax=0;
bool yTrack=true;

void procedura_thread();
void reg(UINT style,WNDPROC lpfnWndProc,int cbClsExtra,int cbWndExtra,HINSTANCE hInstance,HICON hIcon,HCURSOR hCursor,HBRUSH hbrBackground,LPCTSTR lpszMenuName,LPCTSTR lpszClassName);

LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
{

hInst = hInstance;
reg(CS_HREDRAW | CS_VREDRAW | CS_OWNDC,WinProc,0,0,hInst,LoadIcon(NULL,IDI_WINLO GO),LoadCursor(NULL,IDC_ARROW),(HBRUSH)(COLOR_BTNF ACE+0),NULL,"principale");

form1 = CreateWindow("principale","Finestra",WS_MINIMIZEBOX | WS_SIZEBOX | WS_CAPTION | WS_MAXIMIZEBOX | WS_POPUP | WS_SYSMENU,600,300,600,440,NULL,(HMENU)NULL,hInst, NULL);
//label21 = CreateWindow("Edit","",WS_CHILD | ES_LEFT | WS_BORDER | WS_VISIBLE | ES_READONLY | ES_MULTILINE | WS_VSCROLL,1,1,583,203,form1,(HMENU)NULL,hInst,NUL L);

ShowWindow(form1,SW_SHOWNORMAL);
UpdateWindow(form1);
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&procedura_thread,NULL,0,NULL);

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

LRESULT CALLBACK WinProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth;
HDC hdc ;
int i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;

switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;

GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;

si.cbSize = sizeof (si) ;
si.fMask = SIF_RANGE;
si.nMin = 0 ;
si.nMax = nLineMax ;
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;

si.cbSize = sizeof (si) ;
si.fMask = SIF_RANGE;
si.nMin = 0 ;
si.nMax = 2 + iMaxWidth / cxChar ;
SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;

ReleaseDC (hwnd, hdc) ;

// Save the width of the three columns

iMaxWidth = 40 * cxChar + 22 * cxCaps ;
break ;

case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;

// Set vertical scroll bar range and page size

si.cbSize = sizeof (si) ;
si.fMask = SIF_PAGE ;
si.nPage = cyClient / cyChar ;
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;

// Set horizontal scroll bar range and page size

si.cbSize = sizeof (si) ;
si.fMask = SIF_PAGE ;
si.nPage = cxClient / cxChar ;
SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
break ;

case WM_VSCROLL:
si.cbSize = sizeof (si) ;
si.fMask = SIF_ALL ;
GetScrollInfo (hwnd, SB_VERT, &si) ;

iVertPos = si.nPos ;

switch (LOWORD (wParam))
{
case SB_TOP:
si.nPos = si.nMin ;
break;

case SB_BOTTOM:
si.nPos = si.nMax ;
break;

case SB_LINEUP:
si.nPos -= 1 ;
break ;

case SB_LINEDOWN:
si.nPos += 1 ;
break ;

case SB_PAGEUP:
si.nPos -= si.nPage ;
break ;

case SB_PAGEDOWN:
si.nPos += si.nPage ;
break ;

case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break ;

default:
break ;
}

si.fMask = SIF_ALL;
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
GetScrollInfo (hwnd, SB_VERT, &si) ;
if (si.nPos==(si.nMax-si.nPage)+1){yTrack=true;}else{yTrack=false;}

if (si.nPos != iVertPos)
{
ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos), NULL, NULL) ;
UpdateWindow (hwnd) ;
}
break ;

case WM_HSCROLL:
si.cbSize = sizeof (si) ;
si.fMask = SIF_ALL ;
GetScrollInfo (hwnd, SB_HORZ, &si) ;

iHorzPos = si.nPos ;

switch (LOWORD (wParam))
{
case SB_LINELEFT:
si.nPos -= 1 ;
break ;

case SB_LINERIGHT:
si.nPos += 1 ;
break ;

case SB_PAGELEFT:
si.nPos -= si.nPage ;
break ;

case SB_PAGERIGHT:
si.nPos += si.nPage ;
break ;

case SB_THUMBPOSITION:
si.nPos = si.nTrackPos ;
break ;

default :
break ;
}

si.fMask = SIF_POS ;
SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
GetScrollInfo (hwnd, SB_HORZ, &si) ;

// If the position has changed, scroll the window

if (si.nPos != iHorzPos)
{
ScrollWindow (hwnd, cxChar * (iHorzPos - si.nPos), 0, NULL, NULL) ;
UpdateWindow(hwnd);
}
break ;

case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;

// Get vertical scroll bar position

si.cbSize = sizeof (si) ;
si.fMask = SIF_POS ;
GetScrollInfo (hwnd, SB_VERT, &si) ;
iVertPos = si.nPos ;

// Get horizontal scroll bar position

GetScrollInfo (hwnd, SB_HORZ, &si) ;
iHorzPos = si.nPos ;

// Find painting limits

iPaintBeg = max (0, (int)(iVertPos + ps.rcPaint.top / cyChar)) ;
iPaintEnd = min (nLineMax,(int)(iVertPos + ps.rcPaint.bottom / cyChar)) ;

for (i = iPaintBeg ; i <= iPaintEnd ; i++)
{
x = cxChar * (1 - iHorzPos) ;
y = cyChar * (i - iVertPos) ;

TextOut (hdc, 0, y,buf[i],lstrlen (buf[i])) ;

}

EndPaint (hwnd, &ps) ;
break ;

case WM_DESTROY :
PostQuitMessage (0) ;
break ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}





void procedura_thread()
{
char Text[50];

while(nLineMax<60)
{
SetScrollRange(form1, SB_VERT, 0, nLineMax,FALSE);
si.fMask = SIF_ALL;
GetScrollInfo (form1, SB_VERT, &si);

if (yTrack){SetScrollPos(form1, SB_VERT, (si.nMax-si.nPage)+1,FALSE);}

SendMessage(form1,WM_SIZE,0,0);
UpdateWindow(form1);

sprintf(Text,"%d Prova purova prova prova", nLineMax);
strcpy(buf[nLineMax],Text);
Sleep(700);
nLineMax++;
}
}


void reg(UINT style,WNDPROC lpfnWndProc,int cbClsExtra,int cbWndExtra,HINSTANCE hInstance,HICON hIcon,HCURSOR hCursor,HBRUSH hbrBackground,LPCTSTR lpszMenuName,LPCTSTR lpszClassName)
{
WNDCLASS wc;

wc.style = style;
wc.lpfnWndProc = lpfnWndProc;
wc.cbClsExtra = cbClsExtra;
wc.cbWndExtra = cbWndExtra;
wc.hInstance = hInstance;
wc.hIcon = hIcon;
wc.hCursor = hCursor;
wc.hbrBackground = hbrBackground;
wc.lpszMenuName = lpszMenuName;
wc.lpszClassName = lpszClassName;
RegisterClass(&wc);
}

Loading