|
Captain's
VC++ LOG:
This is not a tutorial. But wait! This is my log, started when I was seriously
beginning to do VC++. You might find the one or another hint here - some
topics are hard to find on the net.
Adding a control to a MFC (Doc/View) App
List Control
Calendar Control
How to print integers
How to display a text in an 'edit box'
Call a method in Doc from View
Slider Control: CSliderCtrl
Progressbar: CProgressBar (Progressbar Control 6.0) (Active-X)
Combo Control (Dropdown)
how to return an array from a function
Radio
Bottons: (grouping and checking/unchecking during runtime)
Registry: (reading writing)
Making
a static control clickable: (basic hyperlink)
Getting
the date / time
Ellipse with transparent filling (draw a filled ellipse
with a NULL brush)
Pens, Brushes, filling and text-color
Opening and reading from a file
Useful stuff (strings, numbers etc...)
###################################################################################
Adding a control to a MFC (Doc/View) App: (made with
File -> New -> MFC Appwizard (exe) )
0. Go to the graphical
dialog editor
1. If the control you want is not in the small controls-window (with the
small symbols like arrow, checkbox, radio-button) go to the menu Project
/ Add to project / Components and controls
2. Add the control to your dialog (select a control in the small controls-window
and then 'draw' it in your resource/dialog window
3. Click on the new control, open the wizard with CTRL+W. Go to the 'Message-Maps'-tab,
select the class-name where you want to add the control-methods and double-click
on the message (Messages) you want. Name the new method.
4. Click on the 'member-variables' tab (be sure you're in the right class
(Class name)), select the new control (Control ID's) and click on add
variable.
Name the variable, select a category and variable type. i.e. if you have
an edit box and you simply want to write into it, select 'value' for the
category. So you can simply assign a value to the edit box which is displayed.
If you want to access methods or properties of the control you want a
'control' as category.
Variable type: i.e. edit box: you can select all sort of variable types
like int, CString etc.
But it is not uncommon that there is only one choice. i.e. CSliderCtrl.
top
###################################################################################
List control: (ya know, the stuff that looks like
a table in excel or the right part of windows-explorer)
Add a CListCtrl and associate a member-variable (m_listctrl) to it.
Add this code to your construction section:
LV_COLUMN listColumn; LV_ITEM listItem; char* arCol[3] = { "Column 1", "Column 2", "Column 3" };
listColumn.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM; listColumn.fmt = LVCFMT_LEFT; listColumn.cx = 160;
for( int nColumn = 0; nColumn < 3; nColumn++ ) { listColumn.iSubItem = nColumn; listColumn.pszText = arCol[nColumn]; m_listctrl.InsertColumn( nColumn, &listColumn ); }
// Add list items listItem.mask = LVIF_TEXT; listItem.iSubItem = 0; char* ar1[3] = { "0 / 0", "0 / 1", "0 / 2" }; char* ar2[3] = { "1 / 0", "1 / 1", "1 / 2" }; char* ar3[3] = { "2 / 0", "2 / 1", "2 / 2" };
for( int nItem = 0; nItem < 3; nItem++ ) { listItem.iItem = nItem; listItem.pszText = ar1[nItem]; m_listctrl.InsertItem( &listItem ); m_listctrl.SetItemText( nItem, 1, ar2[nItem] ); m_listctrl.SetItemText( nItem, 2, ar3[nItem] ); }
// add this for full
row selection
ListView_SetExtendedListViewStyle (m_listctrl.m_hWnd, LVS_EX_FULLROWSELECT);
How to read a selected
value:
Within the 'BN_CLICKED' message handler you can use this:
int
nSel = m_listctrl.GetNextItem( -1, LVNI_SELECTED );
AfxMessageBox(m_listctrl.GetItemText ( nSel, 0 ));
Simple adding a row to the list control:
In general see the construction code above.
However VC++ can be a real pain in the a..
If you want to set a CString into a row-item, see listItem.pszText below.
We have to do some casting,
otherwise the compiler cries.
LV_ITEM
listItem;
listItem.mask = LVIF_TEXT;
listItem.iSubItem = 0;
listItem.iItem = rownumber;
listItem.pszText = (char*)(LPCTSTR)(szMsg);
m_listctrl.InsertItem( &listItem );
m_listctrl.SetItemText( rownumber, 1, "-" );
m_listctrl.SetItemText( rownumber, 2, "*" );
For more info go to
the MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmfc98/html/_mfc_clistctrl.asp
top
###################################################################################
Calendar Control 8.0 (Active-X)
Adding a Calendar
Control is very easy.
Add the 'Calendar Control 8.0' to your dialog.
Message maps: i.e.
'Click'.
In the 'OnClick' method
do stuff like this:
int
day = m_cal.GetDay();
int month = m_cal.GetMonth();
int year = m_cal.GetYear();
top
###################################################################################
How
to print intergers:
If you want to have an integer as string you must convert it. Otherwise
you get just a garbled 'value'.
int intval = 1234;
CString text;
szMsg.Format("value = %d", intval);
// do something with it:
// I usually use this below for debugging
// or
display the value in the statusbar
AfxMessageBox(szMsg);
top
###################################################################################
How to display a text in an 'edit box':
Simple!
Add the 'edit box' control to your dialog.
In the wizard: Add a member variable m_textout: Category 'value' and Variable
type 'CString'.
Of course we only do outputs in the View!
If you want to set
the text of the edit box, just do this:
CString msg;
m_out = msg;
UpdateData(FALSE); // IMPORTANT: otherwise the value doesn't show up.
You can of course
display other data aswell. Just select another variable type (wizard ->
member-variable).
top
###################################################################################
Call a method (function) in Doc from View:
CRomeDoc *pDoc = GetDocument();
ASSERT_VALID(pDoc);
int value = pDoc->method();
top
###################################################################################
Slider Control: CSliderCtrl
Add the splider to
your dialog.
Add a member variable of category 'control' and variable type 'CSliderCtrl.
Add a message (wizard -> Message Maps) for NM_CUSTOMDRAW (called when
the slider is moving and the mouse-button is still pressed) and/or NM_RELEASEDCAPTURE
(called when the slider was moved and the mouse button was released).
Get the position with:
int pos = m_sliderctrl.GetPos();
Initializing of the
slider:
m_sliderctrl.SetRange( int slidermin,
int slidermax );
m_sliderctrl.SetTicFreq( int step );
MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmfc98/html/_mfc_csliderctrl.asp
top
###################################################################################
Progressbar: CProgressBar (Progressbar Control 6.0) (Active-X)
see Slider Control.
(note: there are no messages, since it is a passiv control)
m_Progress.SetRange(m_nLower,m_nUpper);
m_Progress.SetStep(m_nStep);
m_Progress.SetPos(m_nLower);
top
###################################################################################
Combo Control (Dropdown - Drop list - Droplist):
Add a Combo Box to your dialog. Add a member variable (Control) to it.
You add a message ( i.e. CBN_SELCHANGE for a message when the value in
the dropdown changed)
and add this to your message-function:
UpdateData(TRUE);
To get the current selection use this:
int idx = m_combohourctrl.GetCurSel();
// remember: UpdateData(TRUE) before!
or if you don't want the index, but the text of the current selection:
CString str;
int idx = m_combohourctrl.GetCurSel();
if( idx < 0 ) return;
m_combohourctrl.GetLBText(
idx, str );
// now you can use int intvalue = atoi(str) ot float fvalue = atof(str)
// to get the numerical value if applicable
CString Out;
Out.Format( "Drop List Selection => index %d\n%s", idx, str
);
AfxMessageBox( Out );
To set an initial value of the dropdown, use this:
m_combohourctrl.SetCurSel(0);
UpdateData(FALSE);
or
CString str = "someitemname";
m_DropDown.SelectString(0,str);
Otherwise the dropdown-value
is empty by default.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_MFC_CListBox.asp
top
###################################################################################
Returning
an array from a function: (how to return an array from a function)
Something really annoying about C++ is that you can't return an array
from a function (method) like one does in Perl or Java. You have to create
the array before calling the function, then call the function, passing
a pointer to the array. Within the function, the array is filled.
Examples:
void CRomeView::test (int* x) { x[0] = 21; x[1] = 10; } void CRomeView::test2 (CString* x) {
x[0] = "text1"; x[1] = "text2"; }
Calling
the function:
int myint[2];
test(myint);
AfxMessageBox( myint[1] );
CString cs[2];
test2(cs);
AfxMessageBox( cs[1] );
After calling the function,
we have the 'return' values in the array we created before.
top
###################################################################################
Radio
Bottons: (grouping and selecting/deselecting during runtime)
Grouping:
Assuming you have 4 radio buttons and you want to make 2 groups. That
means, that you can select either one of the first 2 or one of the second
2.
First make sure that the tab-order of all 4 radio buttons is ascending
(Menu: Layout / Tab Order).
Then open the properties window of the first radio-button (right click
on it -> Properties) and check the Group-checkbox. Make sure the second
radio-botton has the Group-box unchecked. Check the Group-box of the third
and uncheck the Group-box of the fourth. You see where this is going to.
The first one of a radio-button-group has to be set to 'Group'. All
other radio-buttons Group-option is not selected.
Selecting / deselecting:
Just
add a group of radiobuttons to your dialog. Group them or not, it's up
to you.
Go to the wizard and add a member variable. You can choose between a 'value'
and a 'control'.
Note: There is just one member-variable if you have a group!
A 'value' is very neat, since you can directly read the index-value (integer)
of the selected button (starts at 0...).
On the other hand you can just check/select a radio-button by assigning
a value to it.
i.e. you want to set radiobutton #3 in a group of 5, do this:
m_radio = 2; // remember: counting starts at zero
UpdateData(FALSE); // don't forget this: writes the values to the controls
If you just have a single radio-button:
m_radio = 0; // select the radio-button
m_radio = -1; // deselect the radio-button
If you want to read back the choice of the user, don't forget to do
UpdateData(TRUE); // reads the values from the controls
before using the value (m_radio)
somewhere. Just add this in the message handler (BN_CLICKED) for each
radio-button.
You can also use this: m_radioctrl.SetCheck(1);
if you prefer a control.
top
###################################################################################
Registry:
(reading and writing - be very careful not to screw it up!!!)
Setting a value in the registry:
#include <atlbase.h>
// add this to your .h-file
CRegKey key;
DWORD dwvalue= (DWORD)(myinteger);
long nError = key.Create(HKEY_CURRENT_USER, "Software\\CaptainSoft\\myprg");
if(nError == ERROR_SUCCESS) {
// Code here to write values to MyProgram key
key.SetValue( "Hallo Welt", "StringEintrag");
key.SetValue(
dwvalue, "DWORDeintrag");
key.Close();
}
key.Create does create and open the key if it doesn't exist yet, or just
open it in case it is already in the registry.
Reading from the registry:
CRegKey key;
DWORD dwlat, dwlon;
key.Open( HKEY_CURRENT_USER, "Software\\CaptainSoft\\myprg",
KEY_READ);
key.QueryValue( dwlat, "latdir");
key.QueryValue( dwlon, "londir");
key.Close();
top
###################################################################################
Making
a static control clickable: (basic hyperlink)
a.
Add a static-control text or static-image (bitmap) to your dialog.
Go to the properties (right-click on the control) and either change the
text or select the 'type' -> Bitmap and the image (you have to create
the bitmap first). Also check the 'notify' option in the properties!
Then go to the wizard (CRTL-W) and add a BN_CLICKED message to the message-map
of your static-control. Name the function to be called when the control
is clicked.
Now go to the code and change
ON_BN_CLICKED(IDC_LINK,
OnLink)
to
ON_STN_CLICKED(IDC_LINK,
OnLink)
Now go
to the method 'OnLink' and add this:
ShellExecute(NULL, "open",
"http://www.url.com", NULL, NULL, SW_SHOWNORMAL);
If your control is
a simple text, you can change the appearance to a certain extent in the
properties.
i.e. make a small border around it. If your control is a bitmap image,
make the test blue and underline it.
b. If you want it more sophisticated and look like a real link,
try this in your OnPaint method:
CWnd* wnds; wnds = GetDlgItem(IDC_HYPERLINK); //get a pointer to the static control CPaintDC dc2(wnds); // pointer to the device context of the static control CFont f; f.CreateFont( 12, // nHeight 0, // nWidth 0, // nEscapement 0, // nOrientation FW_NORMAL, // nWeight FALSE, // bItalic TRUE, // bUnderline <---- 0, // cStrikeOut ANSI_CHARSET, // nCharSet OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily _T("MS Sans Serif")); // lpszFacename
CFont *pOldFont = (CFont*)dc2.SelectObject(&f); //select the font dc2.SetBkMode(TRANSPARENT); // we want to draw without background dc2.SetTextColor(RGB(0,0,255)); //set the text-color to blue CString xx; m_hyperlink.GetWindowText(xx); //get the text of the hyperlink //you must assign a member control variable to your static dc2.TextOut(0, 0, xx); //(over)write the text in the static control dc2.SelectObject(pOldFont);
Of course you have to make to changes mentioned in a. aswell.
top
###################################################################################
Getting
the date / time:
int curday = COleDateTime::GetCurrentTime().GetDay();
int curmonth = COleDateTime::GetCurrentTime().GetMonth();
int curyear = COleDateTime::GetCurrentTime().GetYear();
int curhour = COleDateTime::GetCurrentTime().GetHour();
int curminute = COleDateTime::GetCurrentTime().GetMinute();
http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/vclib/html/_MFC_COleDateTime.3a3a.GetCurrentTime.asp
top
###################################################################################
Ellipse
with transparent filling (draw a filled ellipse with a NULL brush):
Ellipse
(circles) are filled with the current brush by default. So you have to
set the current brush to a NULL_BRUSH to get an 'empty' ellipse/circle:
CBrush* pOldBrush = (CBrush*)dc.SelectObject(GetStockObject(NULL_BRUSH)
);
CRect rcEllipse( 10,10,200,200 );
dc.Ellipse( rcEllipse );
top
###################################################################################
Pens,
Brushes, filling and text-color:
Here
you see how to create a colored pen for drawing, a colored brush for filling
and how to set the text-color for TextOut:
// do some init
CPen penblue( PS_SOLID,
0, RGB(0,0,240)); //make the pen
LOGBRUSH logBruGreen;
logBruGreen.lbStyle = BS_SOLID;
logBruGreen.lbColor = RGB(0, 170, 0);
logBruGreen.lbHatch = HS_CROSS;
CBrush brugreen;
brugreen.CreateBrushIndirect(&logBruGreen); //make the brush
//main: selecting the objects for drawing
dc.SelectObject( &penblue ); //select the blue pen, i.e. in a loop
dc.SelectObject(&brugreen); //select the green brush, i.e. in a loop
dc.SetTextColor(RGB(0,0,240));
//set the text-color
//do this when you want the text with a transparent background
dc.SetBkMode(TRANSPARENT);
dc.TextOut( xcoordinate, ycoordinate, somecstringtext);
CPen:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmfc98/html/_mfc_cpen.asp
CBrush:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcemfc/htm/cbrush.asp
CDC: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcemfc/htm/cdc.asp
top
###################################################################################
Opening
and reading a file:
char buf[200];
ifstream fin("captain.txt");
fin.seekg(0, ios::beg);
while (!fin.eof()) {
fin.getline(buf,200);
// do something with buf
}
fin.close();
You need to include #include
"fstream.h" !!
top
###################################################################################
Useful
stuff :
char buf[200];
int i = strstr(buf, "somestring"); // see if "somestring"
is in buf
// -> returns NULL if not found, otherwise the position of somestring
char buf2[2];
int i = atoi(buf2); // makes an integer out of buf2 (array)
char buf4[4];
double dub = atof(buf4); // makes an double out of buf4 (array)
|