Win32 API window

Status
Niet open voor verdere reacties.

Dinux

Gebruiker
Lid geworden
20 jan 2010
Berichten
420
Hallo iedereen,

Ik ben een server aan het maken en nu is de bedoeling dat de output van de functie in een soort van zelfgemaakte console komt. Hieronder staat de code tot nu toe. Ik heb alleen een paar problemen. Hoe kan ik er voor zorgen dat na elke actie een output in de edit box komt? De edit box moet ook read-only worden alleen kom ik hier niet echt uit omdat me tekst opmaak dan weer verdwijnd. Kan iemand deze code aanpassen of mij een beetje helpen?
Code:
#include <iostream>
#include <winsock2.h>
#include <time.h>
#include <windows.h>
#include <string.h>

using namespace std;

//
static char szClassName[ ] = "ClassMainApp";
static HINSTANCE g_hInst;

//prototypes
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void StartServer(HWND hEdit);
//void BuildGUI(HWND hwnd);

//int window()
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{

    HWND hwnd;
    MSG messages;
    WNDCLASSEX wincl;

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx (
           0,
           szClassName,
           Console",
           WS_OVERLAPPEDWINDOW,
           CW_USEDEFAULT,
           CW_USEDEFAULT,
           650,
           400,
           HWND_DESKTOP,
           NULL,
           hThisInstance,
           NULL
           );

    ShowWindow (hwnd, nCmdShow);

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

    return messages.wParam;
}

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        case WM_CREATE:
CreateWindow(
        "EDIT",
        "",
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_WANTRETURN,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        hwnd,
        (HMENU)1001,
        g_hInst,
        NULL
    );
    SendDlgItemMessage(hwnd, 1001, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0));
            StartServer(GetDlgItem(hwnd, 1001));
            break;
        case WM_SIZE:
            if(wParam != SIZE_MINIMIZED)
            {
                MoveWindow(GetDlgItem(hwnd, 1001 ), 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
            }
            break;
        case WM_CTLCOLOREDIT:
        {
            HDC hEdit = (HDC)wParam;
            SetTextColor( hEdit, RGB(0, 255,0) );
            SetBkColor  ( hEdit, RGB(0, 0, 0) );
            return (INT_PTR)GetStockObject( BLACK_BRUSH );
        }
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

void StartServer(HWND hEdit)
{
    char *pszText;
    DWORD dwTextLength;

    SetWindowText(hEdit, "starting Server...\r\n");
    //actie
   //laat output op scherm zien 
   //actie
   //laat output op scherm zien
   //actie
   //laat output op scherm zien
}
 
Zo te zien gebik je VC10? Ik dat geval als je proffesional gebruik kan je naar je .rc file gaan op de edit box, read only = TRUE doen.

Verder weet ik niet wat je wilt laten zien, een int een char? onder elkaar of elkaar steeds vervangen. Meer info graag.
 
Nee ik gebruik CodeBlocks waarin helaas geen form editor in zit. Het is de bedoeling dat er een server wordt opgezet en elke actie die wordt uitgevoerd zoals binden met een port moet worden laten zien op het scherm, dus in de edit box. het moet dus onder elkaar en het wordt dan dus een soort van log file. Ik hoop dat het nu een beetje duidelijk is wat ik wil.
 
gebruik je geen resource file? ik weet niet uit mijn hoofd hoe je met pure win32 de edit contorl moet beveiligen maar msdn weet et vast wel.

Voor je andere probleem is makkelijk. Gewoon een functie met AddText maken en die dan de char die erbij moet er bij plakken en dan die in je edit box zetten.

Simpel voorbeeld

char x[200];
char End[1000];

GetDlgItemText (hWnd, IDC_, End) // zoiets
en dan met den C functie strncat // volgens mij de char x erbij plakken
en dan weer SetDlgText.

Ik denk dat het niet makklijker kan
 
zou je die laatste functie even in code willen schrijven please? Ik heb er zelf ook al aan gedacht om zoiets te doen. Maar als ik zoiets probeerde kreeg ik telkens een runtime error. Nee ik gebruik geen recource file en ik zou ook niet weten hoe dat moet/
 
Om een window of child window uitgeschakeld te weergeven moet je de CreateWindow functie roepen waarbij je de WS_DISABLED style hebt toegevoegd aan de dwStyle parameter. Je kunt altijd een window of child window in- of uitschakelen met de EnableWindow functie.

Toch raadt ik jouw aan om een ListBox window te maken met de LBS_NOSEL style eigenschap. Met de SendMessage functie stuur je een LB_INSERTSTRING message, de lParam parameter bevat het bericht dat wordt toegevoegd aan de list box. Je hoeft de list box niet uitgeschakeld te weergeven aangezien het voor de gebruiker niet mogelijk is om de inhoud aan te passen.

Deze methode (of soortgelijke methode maar dan met een SysListView32 window) wordt ook toegepast bij de bekende NSIS installeer programma's. Zo wordt de status van de installatie weergegeven aan de gebruikers. Bij elk bestand dat het installeer programma kopieert wordt er een nieuwe regel toegevoegd aan de list box, bijvoorbeeld: "Extract: bestand.dll... 100%".
 
Ik heb je advies opgevolgd maar nu heb ik het volgende probleem. Als ik deze code:
Code:
SendMessage(GetDlgItem(hwnd, 1001 ), LB_INSERTSTRING, 0, "tekst hier");
uitvoer om een bericht toe te voegen aan de listbox krijg ik een invalid conversion terug. Het tweede probleem is dat ik ook me stijl kwijt ben. Hoe krijg ik de listbox zwart en de tekst erin groen?
 
dit is is een functie voor een tree view met alleen parents dus alles onder elkaar,b egin van een nieuwe ding

Code:
HTREEITEM Parent;   
char name[25];
TV_INSERTSTRUCT tvinsert;  

void AddText()
{
	tvinsert.hParent=NULL;
	tvinsert.hInsertAfter=TVI_ROOT;
	tvinsert.item.mask=TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
	tvinsert.item.pszText = Name;//"Parent";
	tvinsert.item.iImage=0;
	tvinsert.item.iSelectedImage=1;
}

void LoopBefore(HWND hWnd)
{
	AddText();
	Parent=(HTREEITEM)SendDlgItemMessage(hWnd,IDC_TREE1,
                          TVM_INSERTITEM,0,(LPARAM)&tvinsert);
}

je kan het aanroepen door:

Code:
int main()
{
char Buffer[100];
				GetDlgItemText(hWnd, IDC_EDIT1, Buffer, 100);
				strcpy_s (Name,Buffer);
				LoopBefore(hWnd);
}

hoop dat dit helpt
 
Ik heb zoals Dnb voorstelde voor een ListBox gekozen. Ik waardeer je code heel erg maar ik weet momenteel even niet hoe ik dit zou moeten toevoegen aan een listbox. Btw, op het moment dat ik2 keer de functie strcpy_s (); in me code zet krijg ik een runtime error al weet ik niet of dat normaal is :)
 
hmm, het ligt niet aan strcopy(_s), je hebt ergens iets fout gedaan, ik gok zo een beetje dat je

char x[20];

en dan daar een strcopy_s op, => error omdat x geen waarde heeft.

dus

charx[20] = "";

dan zal et werken, anders post je code
 
Het eerste wat je doet in je DialogProc Callback functie is het declareren van je variabelen zodat deze variabelen overal gebruikt kunnen worden binnen de DialogProc Callback functie.

Code:
INT_PTR CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{

    static HWND hwndListBox = NULL;

//En nog meer variabelen

In de DialogProc Callback functie filter je alle binnenkomende berichten. Wanneer er een WM_INITDIALOG bericht binnenkomt roep je onder anderen de GetDlgItem functie om een handle te verkrijgen van jouw list box.

Code:
case WM_INITDIALOG://Hier vindt het initialiseren van je dialog window plaats, hoe jij hier de onderstaande code precies verwerkt is aan jou
{

    hwndListBox = GetDlgItem( hwndDlg, DCW_LISTBOX );//#define DCW_LISTBOX 1001 voor overzichtelijkheid van je code

    if ( hwndListBox != NULL )
    {

        SendMessage( hwndListBox, LB_INSERTSTRING, WPARAM( 0 ), LPARAM( "tekst hier" ) );//"The return value specifies the result of the message processing; it depends on the message sent."

Probeer niet te veel code uit te voeren binnen de WM_INITDIALOG case. Aangezien de hwndListBox variabele statisch gedeclareerd is kun je overal binnen de DialogProc Callback functie een regel toevoegen aan de list box.

Om de kleur te veranderen moet je het WM_CTLCOLORLISTBOX bericht verwerken in jouw DialogProc Callback functie.

Code:
case WM_CTLCOLORLISTBOX:
{

    if ( HWND( lParam ) == hwndListBox )//Mocht je meer dan 1 list box window hebben dan kun je ze hier onderscheiden maar ook met 1 list box raadt ik je aan om deze controle niet over te slaan
    {

        SetTextColor( HDC( wParam ), RGB( 0, 255, 0 ) );//Zet de tekstkleur op groen

        SetBkColor( HDC( wParam ), RGB( 0, 0, 0 ) );//Zet de achtergrond van de tekstkleur op zwart

        return INT_PTR( GetSysColorBrush( COLOR_WINDOWFRAME ) );//"GetSysColorBrush returns a cached brush instead of allocating a new one". Omdat COLOR_WINDOWFRAME zwart als kleur is kunnen we dus de GetSysColorBrush functie gebruiken om te voorkomen dat we een nieuwe brush moeten alloceren
    }

    return FALSE;
}
 
Laatst bewerkt:
Bedankt voor het helpen ik ben al een heel stuk verder. De code die je hebt geschreven hen ik niet letterlijk overgenomen maar alleen verschillende delen. De functie is veranderd in deze: SendMessage(hEdit, LB_INSERTSTRING, WPARAM( -1 ), LPARAM( "tekst" ) ); zodat de volgende regel eronder komt. De opmaak met return INT_PTR( GetSysColorBrush( COLOR_WINDOWFRAME ) ); werkte niet wat de achtergrond werd dan grijs :) maar dat heb ik al opgelost. Waar ik me nog wel over verbaas is het volgende stukje code:
Code:
SendMessage(hEdit, LB_INSERTSTRING, WPARAM( -1 ), LPARAM( "text 1" ) );
SendMessage(hEdit, LB_INSERTSTRING, WPARAM( -1 ), LPARAM( "text 2" ) );
SendMessage(hEdit, LB_INSERTSTRING, WPARAM( -1 ), LPARAM( "text 3" ) );
Sleep(5000);
SendMessage(hEdit, LB_INSERTSTRING, WPARAM( -1 ), LPARAM( "text 4" ) );
Nu had ik verwacht dat er een venster verscheen met text 1 text 2 text 3 (onder elkaar) en dat hij dan 5 seconde wacht en dan ook text 4 print. Maar het duurt gewoon 5 seconde voordat het hele programma verschijn en als het verschijnd dan staat alle text er al, hoe kan dit? En hoe los ik het volgende probleem op:
Code:
int getal = 17;
SendMessage(hEdit, LB_INSERTSTRING, WPARAM( -1 ), LPARAM( getal );
zodat er dus 17 verschijnt in de listbox op het scherm, maar dit werkt niet. Hoe kan ik dat oplossen?
 
Laatst bewerkt:
heb je dat 1e gedaan in de main loop van de window, CASE WM_INTIALOG, waarschijnlijk wel want dan wordt de main loop gedaan voordat de window verschijnt, maak een apparte functie die pas nadat de window is gemaakt wordt aangeorpen.

Verder voor dat getal, je kan kijken of je int naar char kan doen of (char) getal probeert. Ik weet niet wleke error je precies krijgt.
 
Er wordt een functie aangeroepen vanuit de WM_CREATE. Die functie schrijft de berichten weg naar de listbox en daarin had ik de sleep() gezet. Zoiets dus:
Code:
case WM_CREATE:
            StartMain();
            break;
// de StartMain functie:
void StartMain()
{
   SendMessage(hEdit, LB_INSERTSTRING, WPARAM( -1 ), LPARAM( "text 1" ) );
   Sleep(5000);
   SendMessage(hEdit, LB_INSERTSTRING, WPARAM( -1 ), LPARAM( "text 2" ) );
}

Wat betreft de int in de SendMessage functie: ik heb de volgende code uitgevoerd:
Code:
int i = 0;
    do{
        i++;
        SendMessage(hEdit, LB_INSERTSTRING, WPARAM(-1), LPARAM(i));
    }while(i < 10);
ik krijg geen compiler fout terug maar als ik het programma start komt er een runtime error in beeld. "Dit programma werkt niet meer". Hoe kan ik dit oplossen?
 
Het probleem is alleen dat nadat je de SendMessage functie uitvoerd je alleen nog maar de string hebt toegevoegd aan de listbox in het geheugen dit is nog niet op het scherm getekend dat gebeurd pas in de volgende ronde van je Message-loop, maar die vertraag je met 5 seconde. Na vijf seconde wordt alles tegelijk op het scherm getekend.

Je moet waarschijnlijk een oplossing verzinnen met meerdere threads.

Het andere probleem:
Code:
for(int i = 1; i < 11; i++)
{
       SendMessage(hEdit, LB_INSERTSTRING, WPARAM(-1), LPARAM(char(i + 48)));
}
 
het 1e probleem is simpel.

In je WinMain, waar het programma begint:

even simpelweg

doe

DiagloxBox, of welke je ook gebruikt om je window optestarte
en daarna roep je dan jouw functie aan, met een Sleep(3000) in het begin zodat de window tijd heft om op te starte

int to char?
 
Het sleep probleem is inmiddels opgelost maar me tweede probleem nog niet
Code:
for(int i = 1; i < 11; i++)
{
       SendMessage(hEdit, LB_INSERTSTRING, WPARAM(-1), LPARAM(char(i + 48)));
}
Geeft weer terug: "test.exe werkt niet meer" een runtime error dus. En als ik het programma uitvoer zonder dit stukje code gaat alles goed.

@NLScotty
nee het is geen int to char maar int to LPARAM. Als ik namelijk di schrijf:
SendMessage(hEdit, LB_INSERTSTRING, WPARAM(-1), "Hallo");
Krijg ik een compiler error: invalid LPARAM to CHAR conversion.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan