Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Tekstin tulostus Windows-ikkunaan

Sivun loppuun

TVdata [10.12.2011 14:38:01]

#

Miten windows-ikkunassa tulostetaan kuten komentorivillä tämä:

std::cout <<"Hei!";

ja kysytään näin,

int kirjoitus;
std::cin >> kirjoitus;

kun windows ikkuna on tällainen?

#include <windows.h>

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

Ikkunan koodi on Dev-C++:sta.

Metabolix [10.12.2011 14:58:00]

#

Käyttäjälle tulostettavan tekstin voi sijoittaa vaikka STATIC-tyyppiseen kontrolliin. Syötteen lukeminen on vielä hankalampaa, paras tapa olisi varmaan tehdä EDIT-tyyppinen kontrolli eli tekstilaatikko ja tunnistaa sitten, milloin käyttäjä painaa laatikossa enteriä. Kontrolleja käsitellään WinAPI:ssa kuten ikkunoita.

Eli ei ole helppoa eikä tapahdu ollenkaan samalla tavalla kuin komentorivillä. WinAPI-ohjelmointia en suosittelisi kenellekään, kun muut kirjastot (wxWidgets, Qt, GTK) ovat paljon yksinkertaisempia. Graafista ohjelmointia en suosittele sinulle vielä pitkään aikaan, kun et selvästi osaa oikein alkeitakaan kunnolla.

TVdata [10.12.2011 15:32:08]

#

Metabolix kirjoitti:

Kontrolleja käsitellään WinAPI:ssa kuten ikkunoita.

Siis miten?

Metabolix [10.12.2011 15:44:42]

#

Jos nyt välttämättä haluat, voit lukea vaikka jotain WinAPI-opasta. En kuitenkaan usko, että pääset kovin pitkälle, kun et ole vielä opetellut alkeita kunnolla.

TVdata [10.12.2011 15:52:36]

#

Kiitos.
Onko vielä jotain yksinkertaisemmin saatavaa teksti-ikkunaa?

User137 [10.12.2011 19:49:03]

#

TVdata kirjoitti:

Onko vielä jotain yksinkertaisemmin saatavaa teksti-ikkunaa?

Lähtökohtana on että C++ -kielessä juuri mikään ei ole yksinkertaista. Jos koodauksen helppous kiinnostaa ja haluat saada nopeammin jotain aikaan, niin kannattaa tutustua vaikka Lazarus & Freepascaliin
http://lazarus.freepascal.org/

Metabolix [10.12.2011 20:20:07]

#

Enkö juuri hetki sitten luetellut kolmekin helpompaa vaihtoehtoa eli kirjastot wxWidgets, Qt ja GTK? Mutta eivät nekään ole niin paljon helpompia, että sinun kannattaisi niihin koskea. Käytitpä mitä kirjastoa tahansa, alkeet on aivan pakko opetella kunnolla, ennen kuin siitä käyttöliittymästä on paljonkaan iloa.

Jos on aivan hirveä hinku tehdä graafisia tuotoksia, vaikkei osaa vielä mitään, kannattaa kyllä vaihtaa kieltä. Esimerkiksi Pascal (Lazarus-kehitysympäristö), Java (NetBeans-kehitysympäristö) ja C# (Visual C# Express) ovat helpompia vaihtoehtoja.

Deffi [11.12.2011 13:43:04]

#

TVdata kirjoitti:

Kiitos.
Onko vielä jotain yksinkertaisemmin saatavaa teksti-ikkunaa?

Vaikka se konsoli? Siihen voit tulostaa coutilla ja lukea cinillä.

neau33 [13.12.2011 19:03:24]

#

Morjens TVdata!

kokeile lisätä viritelmääsi oheiset pätkät...

//------ tämän rivin jälkeen ----------
#include <windows.h>
//------------- näm rivit -------------
#include <tchar.h>
#include <string>
//-------------------------------------

//------------------ tämän rivin jälkeen --------------------
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

//------------------- nämä rivit ----------------------------
LRESULT CALLBACK EditBoxProc (HWND, UINT, WPARAM, LPARAM);
WNDPROC oldEdit;

LPCTSTR strMsg =
"Kirjoita alla olevaan tekstiruutuun ja paina Enter-näppäintä";

#define IDC_EDIT_BOX 101
HWND hWndEdit1;
//------------------------------------------------------------

//...

    //------------------ tämän rivin jälkeen --------------------
    ShowWindow (hwnd, nFunsterStil);

    //------------------------ nämä rivit -----------------------
    hWndEdit1 = CreateWindow("Edit", "",
    WS_BORDER | WS_CHILD | WS_VISIBLE,
    10, 40, 100, 20, hwnd, (HMENU)IDC_EDIT_BOX, NULL, NULL);
    SetFocus(hWndEdit1);

    oldEdit = (WNDPROC) SetWindowLong (hWndEdit1,
                GWL_WNDPROC, (LONG) EditBoxProc);
    //-----------------------------------------------------------

//...

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   //------- tähän alkuun nämä rivit ----------
   HDC hDC;
   PAINTSTRUCT Ps;
   //------------------------------------------

   switch (message)
   {
      case WM_DESTROY:
         PostQuitMessage (0);
         break;
      //-------------- tähän kohtaan nämä rivit -----------------
      case WM_PAINT:
         hDC = BeginPaint(hwnd, &Ps);
         TextOut(hDC, 10, 10, strMsg, _tcslen(strMsg));
         EndPaint(hwnd, &Ps);
         break;
      //---------------------------------------------------------
      default:
         return DefWindowProc (hwnd, message, wParam, lParam);
   }

    return 0;
}

// ---------------------- ja loppuun nämä rivit ------------------
LRESULT CALLBACK EditBoxProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

   char buffer[65536];
   std::string str;
   int txtlen;

   switch (message)
   {
      case WM_KEYDOWN:
         if (wParam == VK_RETURN)
         {
            txtlen = GetWindowTextLength(hWndEdit1) + 1;
            GetWindowText(hWndEdit1, buffer, txtlen);
            str = buffer;
            MessageBox(NULL, str.c_str(), "MsgBox", MB_OK);
            SetFocus(hWndEdit1);
            SendMessage(hWndEdit1,EM_SETSEL,txtlen,txtlen);
         }
         break;
      default:
         break;
   }

   return CallWindowProc(oldEdit, hwnd, message, wParam, lParam);
}

TVdata [16.12.2011 23:00:38]

#

Selittäisitkö mistä tiedän oikeat paikat?

Triton [16.12.2011 23:46:39]

#

TVdata kirjoitti:

Selittäisitkö mistä tiedän oikeat paikat?

Jos, et kykene hahmottamaan, että mistä mikäkin asia muodostuu, niin sitten perusohjelmointitaidoissa on niin paljon puutteita, että on turha yrittääkään mitään tuollaista...

jimi-kimi [17.12.2011 01:49:33]

#

Aloita siitä pythonista / C++ perusteista (+ QT ja tee pikkupelejä [tetris tulee olemaan vaikea]). P*skinta p*skaa win32 opettelu tulee oleman ilman perusteellista ymmärrystä edeltävistä aiheista. En tarkoita nyt vain C++ hyvää ymmärrystä.

JaskaP [17.12.2011 17:58:14]

#

jimi-kimi kirjoitti:

P*skinta p*skaa win32 opettelu tulee oleman ilman perusteellista ymmärrystä edeltävistä aiheista.

Paskinta paskaa tuo näyttää olevan vaikka perusteellinen ymmärrys ohjelmoinnista onkin.

En ole koskaan Win32 API:lla koodannut, mutta kun katsoo koodia niin mitä vit**a?-fiilis on vahva. Oliko suunnittelu mennyt 80-luvulla pieleen eikä sitä enää voinut kokonaan uudistaa vai mikä lienee?

Grez [17.12.2011 18:20:12]

#

Enpä mä nyt tiedä onko tuo sen kummallisempaa kuin muillekaan käyttiksille. Sitä vartenhan erilaisia alustoja (Qt, .Net, Java, yms) tehdään, että koodaajan ei tarvitsisi välittää tuon tason apeista.

Sitä paitsi omasta mielestäni Win32 APIlla ohjelmointi ei ole edes kovin konstikasta. Toki jos lyödään läjä koodia eteen, josta ei tiedä miksi siinä tehdään asioita, niin kyllähän se ankealta näyttää.

Plus täytyy muistaa, että tuo on Neaun koodi ja ne näyttää aina oksennuksilta kielestä riippumatta ;D Sori Neau, ei millään pahalla.

Triton [17.12.2011 19:25:47]

#

No, ehkä kuitenkin pääpointti tässä kohtaan on se, että jos kokeneemmatkaan ohjelmoijat eivät lähtisi suoraan ohjelmoimaan näin matalantason API:lla käyttöliittymiä, niin tuskin kannattaa täysin noviisinkaan ohjelmoida... Yleensä kun lähtee opettelemaan jotain liian mutkikasta, koski se sitten ohjelmointia tai ei, mielenkiinto lopahtaa asiaa kohtaan hetkessä. Sama peruskuvio toistuu aina, kun 12 v. jonne tulee selittämään, että haluaa ohjelmoida 3D-pelin.

ErroR++ [17.12.2011 20:22:57]

#

Grez kirjoitti:

Plus täytyy muistaa, että tuo on Neaun koodi ja ne näyttää aina oksennuksilta kielestä riippumatta.

Oksennukselta? Oli kieli sitten mikä tahansa, aina ihan samoja funktioiden nimiä siinä on vaan varustettu erilaisilla konstanteilla yms.

Triton [17.12.2011 20:54:03]

#

ErroR++ kirjoitti:

Grez kirjoitti:

Plus täytyy muistaa, että tuo on Neaun koodi ja ne näyttää aina oksennuksilta kielestä riippumatta.

Oksennukselta? Oli kieli sitten mikä tahansa, aina ihan samoja funktioiden nimiä siinä on vaan varustettu erilaisilla konstanteilla yms.

Mikäköhän tuossa jäi ymmärtämättä? Jos koodaa käyttämällä huonoja koodauskonventioita, niin koodista kuin koodista saa oksennuksen näköistä. On tietenkin kieliä, kuten C++, josta saa kaksikertaa helpommin sekavaa...

JaskaP [17.12.2011 23:19:23]

#

Grez kirjoitti:

Sitä paitsi omasta mielestäni Win32 APIlla ohjelmointi ei ole edes kovin konstikasta.

Joo, ei se varmaan mitenkään erityisen hankalaa ole, mutta kyllä koodari-paran pitäisi ainakin hetken olla WTF kun puuttuu standardi main-funktio ja lukee:

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

Itse kävisin kurkkaamassa <windows.h> että mitä kummaa. Ja mitä noi LRESULT CALLBACK ym. ovat.

Ei standardia ole tietenkään pakko noudattaa, mutta olisi ihan kiva tietää mitä tuolla voitetaan.

Vertailu samantason koodiin:

/*
  Simple Xlib application drawing a box in a window.
  gcc input.c -o output -lX11
*/

#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
  Display *d;
  Window w;
  XEvent e;
  char *msg = "Hello, World!";
  int s;

                       /* open connection with the server */
  d = XOpenDisplay(NULL);
  if (d == NULL) {
    fprintf(stderr, "Cannot open display\n");
    exit(1);
  }

  s = DefaultScreen(d);

                       /* create window */
  w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 200, 200, 1,
                          BlackPixel(d, s), WhitePixel(d, s));

                       /* select kind of events we are interested in */
  XSelectInput(d, w, ExposureMask | KeyPressMask);

                       /* map (show) the window */
  XMapWindow(d, w);

                       /* event loop */
  while (1) {
    XNextEvent(d, &e);
                       /* draw or redraw the window */
    if (e.type == Expose) {
      XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);
      XDrawString(d, w, DefaultGC(d, s), 50, 50, msg, strlen(msg));
    }
                       /* exit on key press */
    if (e.type == KeyPress)
      break;
  }

                       /* close connection to server */
  XCloseDisplay(d);

  return 0;
}

User137 [18.12.2011 00:29:10]

#

API-kikkailut on nörteille :D Ikkunan luonti Lazaruksella:

ikkuna := TForm.Create;

Tärkeintä lienee, tarvitsetko oikeasti joka kerta kustomoida ikkunan luonnin komento komennolta? WinAPI:n kanssa on niin paljon tavaraa joka toistuu joka kerta. Käyttää dll-funktioita ja sen erikois-vakioita suoraan raakana... Ohjelmoijalle on suunnaton helpotus jos sen saa nidottua yhteen luokkaan joka tekee sen kaiken sun puolesta.

JaskaP:n koodi näyttää jo kätevämmältä, muttei vielä käytä olio-ohjelmoinnin hienouksia.

Triton [18.12.2011 00:40:19]

#

Niin ja jos haluaa päästä lopustakin mielenterveydestään, niin voihan aina kaivaa sen editorin esiin ja näpytellä kaikki suoraan assemblerille :D

Grez [18.12.2011 00:45:33]

#

Jotkut sitäkin harrastaa http://www.grc.com/smgassembly.htm

Metabolix [18.12.2011 01:44:16]

#

User137 kirjoitti:

JaskaP:n koodi näyttää jo kätevämmältä, muttei vielä käytä olio-ohjelmoinnin hienouksia.

JaskaP:n koodin tarkoitus lienee vain näyttää, että WinAPI on jopa omassa sarjassaan sekava. Xlib-versiossa (eli Linuxin "matalalla tasolla") ohjelman kulku on ilmeinen kenelle tahansa, joka ymmärtää C:stä edes jotain. WinAPI-versio vaatii enemmän taustatietoa mm. siksi, että tietotyypit on nimetty huonosti ja yksinkertainenkin ohjelma käyttää callbackia.

neau33 [19.12.2011 08:29:50]

#

Grez kirjoitti:

...
Plus täytyy muistaa, että tuo on Neaun koodi ja ne näyttää aina oksennuksilta kielestä riippumatta ;...

Grez@ oikein arvasit, se oksennus oli tarkoitettu päällesi...

jalski [21.12.2011 13:10:11]

#

Minulla ei Windows API:sta hirveästi kokemusta ole, mutta OS/2:n PM ohjelmointi on hyvin samankaltaista. OS/2:n PM ohjelmassa tosin ei tarvita WinMain funktiota ja piirtäminen sekä koordinaatisto on toteutettu hiukan erilailla.

OS/2:n C:llä ohjelmointi on kohtuullisen suoraviivaista valmiiden headereiden ja macrojen kanssa, mikäli ymmärrys toiminnan perusteista on kohtuullisesti hallinnassa.

TVdata [21.12.2011 14:31:22]

#

En tee noilla enää yhtään mitään. En ainakaan halua jotain win-DOSeja applen koneelle edes rinakkaiseksi tilaa vieämään.
Kiitos siis ohjelmointikielistä.

ErroR++ [08.01.2012 20:29:01]

#

Tämä kannattanee lukea: https://www.ohjelmointiputka.net/koodivinkit/vinkki.php?id=24467
Olen itse kehittelemässä itselleni pientä kirjastoa ikkunoiden käsittelyyn C++:lla ja projekti on edistynyt. (Olen ymmärtänyt alkeet WinAPI:sta.)

Kyllähän tuossa JaskaP:n koodissakin on kommentti "Event loop". Se vastaa Windows -ikkunan MessageLoop:ia. Mutta onhan tuo paljon yksinkertaisempi.

jalski [08.01.2012 20:50:43]

#

C++ ohjelmoijalle suosittelisin tutustumaan: C++ materiaalia, mukaan lukien WinAPI tutoriaaleja

Metabolix [08.01.2012 20:55:28]

#

Suosittelisin unohtamaan sen WinAPI:n. Siinä ajassa, joka menee WinAPI:n alkeiden oppimiseen, voisi opetella jotain parempaa kirjastoa paljon pidemmälle ja koodata hienompia, vähemmän bugisia ohjelmia.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta