[C++] Creating an edit box with my own procedure?

Pages: 12
Ahh, okay. Then in that case I'll stick with the normal stuff at least until I understand it... and have it memorized.

Understood. Frankly I find the entire method rather large, so I made a header file for each procedure in my program. It requires a few uses of extern, but it keeps things aranged.

Two summers ago I bought myself VS Pro 2008 - but I find CodeBlocks easier to use.

Have you made MSVC++ the compiler, and C::B the IDE, or do you use the default compiler?

If you are interested, I can show you how to do command line compiling with it.

I would very much appreciate that. :)
I use the default compiler gcc/g++ mingw GCC whatever, as its fine for me. I modified that last program I posted to read in its own source code file Main.cpp and display it. Here are the directions for command line compiling the modified code, which I'll post after these directions. This is fun.

To do command line compiling you need to invoke the various files in the compiler ‘tool chain’ from a command prompt window. For this to work Windows must be able to find the various binaries that will compile your source code. The first thing I do is create a directory for my source code. I always make a ‘Code’ directory right off my C:\ Drive like so…

C:\Code

Then I make subdirectories for my various programming languages and development environments. I have this for Code::Blocks…

C:\Code\CodeBlks

Note that I’m and old timer from the 16 bit DOS days, and I try at all costs to avoid spaces in directories or file and directory names greater than 8 characters. The necessity for this is becoming less all the time, but I still do it to avoid problems. For this project, which I named ‘Meesa’, I made the following directory…

C:\Code\CodeBlks\Meesa

Put Main.cpp and WinTypes.h there. Make sure these files (included) are named that way exactly. The next step is to create a batch file and put it in that directory, and for lack of a better name call it Meesa.bat. This batch file should when executed (I put a shortcut to it on my desktop) change the directory to where you have your source code, temporarily alter the system PATH specification so that cmd.exe can find the compiler and libs, and finally open a command prompt window. Here is the batch file I created for compiling the Meesa project which is Main.cpp and WinTypes.h…

1
2
3
4
CD\
cd C:\Code\CodeBlks\Meesa
PATH=%PATH%;C:\Program Files\CodeBlocks\MinGW\bin;C:\Program Files\CodeBlocks\MinGW\lib
C:\Winnt\system32\cmd.exe


Note that I’m using an old Windows 2000 laptop to write this, so your bottom line should reflect a valid path for your system to cmd.exe. Also, note that I’m using the mingw GNU gcc/g++ compiler suite instaled in the default location by my Code::Blocks install. These directions will only work for this compiler. Microsoft compilers have other command line syntax and options. If you installed this software somewhere else, you’ll have to alter the paths in this batch file accordingly.

Here is the command line to compile & link the Meesa project with optimizations for stripping symbols from the executable (minimizes size) and small code size…

C:\Code\CodeBlks\Meesa>g++ Main.cpp -o "Meesa.exe" -mwindows -s –Os

It will take several seconds to run. When finished, if there are no errors, you’ll just see the cursor come back in the command line Window. If you then do a dir command you should see Meesa.exe…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
C:\Code\CodeBlks\Meesa>dir
 Volume in drive C is Main
 Volume Serial Number is 881C-5BB1

 Directory of C:\Code\CodeBlks\Meesa

02/08/2011  10:48a      <DIR>          .
02/08/2011  10:48a      <DIR>          ..
02/08/2011  10:34a      <DIR>          .objs
02/08/2011  10:34a               6,349 main.cpp
02/08/2011  10:36a                 146 Meesa.bat
02/08/2011  10:47a                 943 Meesa.cbp
02/08/2011  10:43a                 187 Meesa.depend
02/08/2011  10:48a               8,704 Meesa.exe
02/08/2011  10:47a                 347 Meesa.layout
02/08/2011  10:21a               8,123 Output.txt
01/24/2011  10:57p              10,769 TonyAz.txt
02/08/2011  10:31a                 971 WinTypes.h
               9 File(s)         36,539 bytes
               3 Dir(s)  49,073,025,024 bytes free

C:\Code\CodeBlks\Meesa>


I’m seeing an 8704 byte exe. You can run it from the command prompt if you like. It should read in Main.cpp (its source code file) and display it in a scrollable screen.
Here is WinTypes.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//WinTypes.h
#ifndef WINTYPES_H
#define WINTYPES_H
#define dim(x) (sizeof(x) / sizeof(x[0]))

typedef struct           WindowsEventArguments
{
 HWND                    hWnd;
 WPARAM                  wParam;
 LPARAM                  lParam;
 HINSTANCE               hIns;
}WndEventArgs,           *lpWndEventArgs;

long fnWndProc_OnCreate  (lpWndEventArgs Wea);
long fnWndProc_OnSize    (lpWndEventArgs Wea);
long fnWndProc_OnVScroll (lpWndEventArgs Wea);
long fnWndProc_OnPaint   (lpWndEventArgs Wea);
long fnWndProc_OnClose   (lpWndEventArgs Wea);

struct EVENTHANDLER
{
 unsigned int            Code;
 long                    (*fnPtr)(lpWndEventArgs);
};

const EVENTHANDLER EventHandler[]=
{
 {WM_CREATE,             fnWndProc_OnCreate},
 {WM_PAINT,              fnWndProc_OnPaint},
 {WM_SIZE,               fnWndProc_OnSize},
 {WM_VSCROLL,            fnWndProc_OnVScroll},
 {WM_CLOSE,              fnWndProc_OnClose}
};
#endif 


and Main.cpp (please name it that way...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//Main.cpp
#include      <windows.h>
#include      <stdio.h>
#include      <string.h>
#include      "WinTypes.h"


long fnWndProc_OnCreate(lpWndEventArgs Wea)     //Offset   What's Stored There
{                                               //================================
 unsigned int iLineCount=0,i,iRet=0;            //0  -  3  iLineCount
 char szBuffer[176];                            //4  -  7  ptrPtrBuffer
 char** ptrPtrBuffer=NULL;                      //8  -  11 cyChar
 HFONT hFont,hTmp;
 FILE* fp1=NULL;
 TEXTMETRIC tm;
 HDC hDC;

 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
 fp1=fopen("Main.cpp","r");
 if(fp1)
 {
    do
    {
     iRet=(int)fgets(szBuffer,176,fp1);
     if(!iRet)
        break;
     else
        iLineCount++;
    }while(1);
    rewind(fp1);
    if(iLineCount)
    {
       SetWindowLong(Wea->hWnd,0,iLineCount);
       ptrPtrBuffer = (char**)GlobalAlloc(GPTR, sizeof(char*) * iLineCount);
       if(ptrPtrBuffer)
       {
          SetWindowLong(Wea->hWnd,4, (long)ptrPtrBuffer);
          for(i=0; i<iLineCount; i++)
          {
              fgets(szBuffer,176,fp1);
              ptrPtrBuffer[i]=(char*)GlobalAlloc(GPTR,sizeof(char)*(strlen(szBuffer)+1));
              strcpy(ptrPtrBuffer[i],szBuffer);
          }
       }
       hDC=GetDC(Wea->hWnd);
       hFont=CreateFont(18,0,0,0,FW_BOLD,0,0,0,0,0,0,2,0,"Courier New");
       hTmp=(HFONT)SelectObject(hDC,hFont);
       GetTextMetrics(hDC,&tm);
       SetWindowLong(Wea->hWnd,8,(long)tm.tmHeight);
       DeleteObject(SelectObject(hDC,hTmp));
       ReleaseDC(Wea->hWnd,hDC);
    }
    else
    {
       fclose(fp1);
       return -1;    //will cause CreateWindow() down in WinMain() to fail.
    }
    fclose(fp1);
 }
 else
    return -1;  //will cause CreateWindow() down in WinMain() to fail.

 return 0;
}


long fnWndProc_OnSize(lpWndEventArgs Wea)
{
 int iLinesVisible,iLineCount;
 unsigned int cyChar;
 SCROLLINFO si;

 ZeroMemory(&si, sizeof(SCROLLINFO));
 iLineCount=(unsigned int)GetWindowLong(Wea->hWnd,0);
 cyChar=(unsigned int)GetWindowLong(Wea->hWnd,8);
 iLinesVisible=HIWORD(Wea->lParam)/cyChar;
 si.cbSize = sizeof(SCROLLINFO);
 si.fMask =   SIF_RANGE|SIF_PAGE;
 si.nMin = 0;
 si.nMax = iLineCount-1;
 si.nPage=iLinesVisible;
 if(si.nMax<0)
    si.nMax=0;
 SetScrollInfo(Wea->hWnd,SB_VERT,&si,TRUE);
 if(iLinesVisible<=iLineCount)
    InvalidateRect(Wea->hWnd,NULL,TRUE);

 return 0;
}


long fnWndProc_OnVScroll(lpWndEventArgs Wea)
{
 int iVScrollPos;
 SCROLLINFO si;

 ZeroMemory(&si, sizeof(SCROLLINFO));
 si.cbSize = sizeof(SCROLLINFO);
 si.fMask=SIF_ALL;
 GetScrollInfo(Wea->hWnd,SB_VERT,&si);
 iVScrollPos=si.nPos;
 switch(LOWORD(Wea->wParam))
 {
  case SB_LINEUP:
    if(si.nPos>si.nMin)
       si.nPos--;
    break;
  case SB_PAGEUP:
    si.nPos = si.nPos - si.nPage;
    break;
  case SB_LINEDOWN:
    if(si.nPos<si.nMax)
       si.nPos++;
    break;
  case SB_PAGEDOWN:
    si.nPos = si.nPos + si.nPage;
    break;
  case SB_THUMBTRACK:
    si.nPos=si.nTrackPos;
    break;
 }
 si.fMask = SIF_POS;                           // Set the position and then retrieve it.  Due to adjustments
 SetScrollInfo(Wea->hWnd, SB_VERT, &si, TRUE); // by Windows it may not be the same as the value set.
 GetScrollInfo (Wea->hWnd, SB_VERT, &si);
 if(si.nPos != iVScrollPos)                    // If the position has changed, scroll the window and update it
    ScrollWindow(Wea->hWnd, 0,GetWindowLong(Wea->hWnd,8)*(iVScrollPos-si.nPos), NULL, NULL);

 return 0;
}


long fnWndProc_OnPaint(lpWndEventArgs Wea)
{
 unsigned int iLineCount,i,iStart,iFinish,iLine,iPos;
 TCHAR** ptrPtrBuffer=NULL;
 HFONT hFont,hTmp;
 PAINTSTRUCT ps;
 SCROLLINFO si;
 long cyChar;
 HDC hDC;

 hDC=BeginPaint(Wea->hWnd,&ps);
 iLineCount=(unsigned int)GetWindowLong(Wea->hWnd,0);
 ptrPtrBuffer=(char**)GetWindowLong(Wea->hWnd,4);
 cyChar=GetWindowLong(Wea->hWnd,8);
 si.cbSize = sizeof(SCROLLINFO);
 si.fMask  = SIF_POS;
 GetScrollInfo(Wea->hWnd, SB_VERT, &si);
 iPos=si.nPos;
 iStart=ps.rcPaint.top/cyChar;
 iFinish=ps.rcPaint.bottom/cyChar;
 hFont=CreateFont(18,0,0,0,FW_BOLD,0,0,0,0,0,0,2,0,"Courier New");
 hTmp=(HFONT)SelectObject(hDC,hFont);
 SetBkMode(hDC,TRANSPARENT);
 for(i=iStart;i<=iFinish;i++)
 {
     iLine=iPos+i;
     if(iLine<iLineCount)
        TextOut(hDC,0,i*cyChar,ptrPtrBuffer[iLine],strlen(ptrPtrBuffer[iLine])-1);
 }
 DeleteObject(SelectObject(hDC,hTmp));
 EndPaint(Wea->hWnd,&ps);

 return 0;
}


long fnWndProc_OnClose(lpWndEventArgs Wea)
{
 unsigned int iLineCount;
 char** ptrPtrBuffer=NULL;
 unsigned int i;

 iLineCount=(unsigned int)GetWindowLong(Wea->hWnd,0);
 ptrPtrBuffer=(char**)GetWindowLong(Wea->hWnd,4);
 for(i=0; i<iLineCount; i++)
     GlobalFree(ptrPtrBuffer[i]);
 GlobalFree(ptrPtrBuffer);
 DestroyWindow(Wea->hWnd);
 PostQuitMessage(0);

 return 0;
}


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 WndEventArgs Wea;

 for(unsigned int i=0; i<dim(EventHandler); i++)
 {
     if(EventHandler[i].Code==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(&Wea);
     }
 }

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


int WINAPI WinMain(HINSTANCE hIns,HINSTANCE hPrevIns,LPSTR lpszArgument,int iShow)
{
 char szClassName[]="ScrollWindow";
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 wc.lpszClassName=szClassName;                          wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX);                         wc.style=0;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);               wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);            wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);  wc.cbWndExtra=12;
 wc.lpszMenuName=NULL;                                  wc.cbClsExtra=0;
 RegisterClassEx(&wc);
 hWnd=CreateWindow(szClassName,szClassName,WS_OVERLAPPEDWINDOW|WS_VSCROLL,50,50,1200,900,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 UpdateWindow(hWnd);
 while(GetMessage(&messages,NULL,0,0))
 {
       TranslateMessage(&messages);
       DispatchMessage(&messages);
 }

 return messages.wParam;
}
Now I need to see if I can modify my PowerBASIC code with this somewhat altered message cracking scheme you kind of got me working with...
Thank you very much. I'll be trying that sometime after I re-write my code. I was having some odd errors, so I recreated my project, and I accidentally overwrote main.cpp. So now I'm having to re-create some stuff that I did over the past few days, as I hadn't backed up in just over a week. Hopefully this teaches me to back up more often.
Bummer! Double bummer!!
Okay, for future viewers, here is the code I came up with to move the scrollbar should an out of view window be focused.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
void chkScrollPos(HWND hwnd){
  //This function checks wheter or not the newly focused window is out of view.
  //If it is, this function will scroll up/down based on whether the window is <67/>367...

  /*This works by first calculating where the newly focused window is. To do this we must
  **first take the top position of the settings window (Found with FindWindow()) and the 
  **edit box, and then calculate this together. Because GetWindowRect() bases the numbers 
  **off of the top left of the screen, the minimum in view is always 67, and the maximum is
  **367.
	
  **If the box requires scrolling up, then windowPos (Settings window top - edit window top)
  **is less than 67, if we need to scroll down, it will be higher than 367. If statements
  **cause this to be taken care of.

  **The first part of calculating whether the window is in view is to get where the scroll
  **position needs to be. This requires taking the 67/367 number and subtracting windowPos
  **from it. ABS() is used so that no negative numbers will occur. From there we take that 
  **value and +/- (Depending on up/down) that value from the original nPos of the scrollbar 
  **Then we update the scrollbar position, and the window position to that of nPos.
  */

  RECT editBox, settingsWin;
  GetWindowRect(hwnd, &editBox);
  GetWindowRect(FindWindow(_T("settingsWindow"), _T("Settings")), &settingsWin);
	
  int windowPos=editBox.top-settingsWin.top;

  if(windowPos<67 || windowPos>367){

    int scrollPos=0;
  
    SCROLLINFO vsi;
    ZeroMemory(&vsi, sizeof(SCROLLINFO));
    vsi.cbSize=sizeof(SCROLLINFO);
    vsi.fMask=SIF_ALL;

    GetScrollInfo(glbWin.vScroll, SB_VERT, &vsi);

    if(windowPos<67){
      int scrollPos=abs(67-windowPos);

      vsi.fMask=SIF_POS;
      vsi.nPos-=scrollPos;
      SetScrollInfo(glbWin.vScroll, SB_VERT, &vsi, true);

      SetWindowPos(glbWin.vScrollContent,HWND_TOPMOST,0,-1*vsi.nPos,0,0,
        SWP_NOSIZE|SWP_NOZORDER);
    }
    else if(windowPos>367){
			
      int scrollPos=abs(367-windowPos);
			
      vsi.fMask=SIF_POS;
      vsi.nPos+=scrollPos;
      SetScrollInfo(glbWin.vScroll, SB_VERT, &vsi, true);

      SetWindowPos(glbWin.vScrollContent,HWND_TOPMOST,0,-1*vsi.nPos,0,0,
        SWP_NOSIZE|SWP_NOZORDER);
    }
  }
}


I call this everytime the window is focused, and everytime a character is inputed into the editbox. (Valid or not)

Also, I didn't even need to intercept the [Tab] message, as this takes care of it. I did however like Freddie's [Up]/[Down] also rotating though the boxes, so that was implimented.

Thanks for all the help Freddie!
Last edited on
Topic archived. No new replies allowed.
Pages: 12