C++ Win32 Getting the integer value from a text field - c++

I've been writing a simple Stock Market program to help me learn Win32 programming, but I am struggling to learn how to retrieve integers from an edit control. I've learned how to retrieve strings from an edit control using GetWindowText. According to the MSDN documentation I need to use the GetDlgItemInt function.
The code below I have the user select a company(which I got working for strings) to show company stock information. I have another edit control to have the user type in the amount of shares they'd want to purchase. I want to take this value to calculate the cost of shares and display the result to the user.
HWND hEditSearchCompanies;
HWND mainWindow; //Parent Window
RECT rect;
BOOL fRelative;
BOOL fError;
rect.left = 200;
rect.right = 600;
rect.top = 50;
rect.bottom = 400;
case WM_COMMAND:
{
case IDC_CALCULATETYPESHARES:
{
int sharesInputed = GetDlgItemInt(hEditSearchCompanies, IDC_EDITTYPESHARES, &fError, fRelative);
swprintf_s(SharesInputedBuffer, 20, L"%d", sharesInputed);
InvalidateRect(mainWindow, &rect, FALSE);
}
break;
case IDC_COMPANYINFOBUTTON:
{
int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_COMPANYCODEDIT));
if (len > 0)
{
wchar_t wcEditBuffer[256];
GetWindowTextW(hEditSearchCompanies, wcEditBuffer, len + 1);
Company SearchForCompany = SearchStrings(hwnd, wcEditBuffer);
PrintCompanySearchResults(ChildHDC, SearchForCompany, inputRect);
}
}
}
break;
case WM_PAINT:
{
TextOutW(ChildHDC, x, y, sharesInputedBuffer, wcslen(sharesInputedBuffer));
}
I then want to use the sharesInputed value to display the numbers like so:
int purchaseCost = sharesInputed * company.PricePerShare;
...//Display result to the user
However sharesInputed is always returning zero. I'll put in, say 50 shares. If a company's price per share cost is $63.13, my program should be printing $3,156.50, but sharesInputed is always equal to zero whenever I hit my button to calculate the cost.
MSDN documentation doesn't really have any troubleshooting tips for GetDlgItemInt, and have debugged my program numerous times, but still get 0. Looked around and found a few reasons for this but none have worked for me.
I am not getting any error messages or warnings based on my sharesInputted value.
Hopefully I provided enough code. My control ids match for the windows and buttons.
Thanks!

Paul Sanders has correct answer. GetDlgItemInt wants the parent window. I was giving the window of my edit control instead, and now I'm getting the correct values.
Cheers!

Related

When I click the console, the cursor shows up again. How can I prevent that?

I'm still new to this. so I'm basically on a visual studio project. something called a console application.
#include <windows.h>
#include <iostream>
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coords;
void setcursor(bool visible, DWORD size) { //if we set it to (0,0) in main. the cursor won't be there anymore. the size becomes 20, and it no longer becomes visible? that's the gist of it.
CONSOLE_CURSOR_INFO lpCursor;
if (size == 0) size = 20; //makes the cursor bigger so it won't show?
lpCursor.bVisible = visible;
lpCursor.dwSize = size;
SetConsoleCursorInfo(console, &lpCursor);
}
void gotoxy(int x, int y) { //to change the coordinates the text outputs to on the cmd
coords.X = x;
coords.Y = y;
SetConsoleCursorPosition(console, coords);
}
this thing(method?), below, called the "setcursor". after i make the cmd screen thing bigger and then even after I minimize it again afterwards. it stops working. the cursor thing appears again as though i never had that method set up. how do i make the cursor go for good.
int main()
{
gotoxy(4, 4);
setcursor(0, 0); //makes that cursor on the console that awaits your text input go invisible or something.
int x;
std::cin >> x;
std::cout << x;
}
The cursor in the command window will redisplay when you resize or minimize/restore the command window. You would need to recall this function setcursor(...) on every window shape change to make it invisible again.
The SetConsolCursorInfo function will reject a cursor size of 0. This is why you test for that and, prevent it in this line if (size == 0) size = 20;
Based on JimmyNJ's answer. I figured that I need a way to detect window size changes, cause that void thinge resets back to 0 by itself.
so i went ahead searched up questions on stack overflow on to that endeavor.
link
I tried something with the answer given in the question above.
It detects changes in the window buffer size (I have no idea what this means), perhaps the screen resolution?
Declare this above main()
HWND g_hWindow = GetConsoleWindow();
void CALLBACK EventProc(HWINEVENTHOOK hook, DWORD event, HWND wnd, LONG object, LONG child, DWORD thread, DWORD time) {
setcursor(0, 0);
}
and inside main() write this:
HWINEVENTHOOK eventHook = SetWinEventHook(EVENT_CONSOLE_LAYOUT, EVENT_CONSOLE_LAYOUT, NULL, EventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
if (eventHook != 0) {
setcursor(0, 0);
}
Note that in the console game i am making, i have that 'if' in a do-while loop. Also this doesn't fix things properly. As again that void thinge likes to reset itself to zero. but when it does, this fixes it.

Correct input of a phone number with an input mask

Asked the last question, regarding the mask and how to put the cursor at the end of the typed text, but did not receive an answer. Trying to figure it out on my own, I realized that the question was asked very superficially. So. I tried to delve into the logic, looked at examples on different sites.
ui->lineEdit_newClientPhone->setInputMask("+7\\(999\\)999\\-99\\-99;_");
What was my original idea - when you click the mouse, or when you get focus, check the line in a loop and put the cursor in the place of the first "__". The idea failed very quickly, as soon as I debugged the line ui->lineEdit->text() , and realized that the line consists only of the characters that are in the mask, without the "filler" (_). As a result, I had the line +7()--. The next idea was this, after much torment: I tried to come up with some complex mathematical calculations, like going through a cycle from the end of the string, as soon as part of the string becomes not equal to '(' or ')' or '-' - calculate the position cursor. (considering, again, the characters "( ) -") It seems that something even happened:
if(event->type() == QEvent::MouseButtonPress){
int a = ui->lineEdit_newClientPhone->text().length();
switch(a){
case 6: case 7: case 8:
ui->lineEdit_newClientPhone->setCursorPosition(a - 3);
break;
case 9: case 10:
ui->lineEdit_newClientPhone->setCursorPosition(a - 2);
break;
case 11: case 12:
ui->lineEdit_newClientPhone->setCursorPosition(a - 1);
break;
case 13: case 14:
ui->lineEdit_newClientPhone->setCursorPosition(a);
break;
}
}
But still hit some strange behavior, because when you click the mouse, the cursor is STILL put in the place where the mouse was poked. Despite the fact that putting the above switch into a button seems to work correctly.
I even tried to process elementary logic - when receiving focus, the cursor would receive index 4, that is, it would move to the first position necessary for introduction - but here the situation is the same as described above.
Maybe i need to use the validator directly with the line? Now there is a validator, here is its code:
QRegularExpression numberRegex ("^\\+\\d{1,1}\\(\\d{3,3}\\)\\d{3,3}\\-\\d{2,2}\\-\\d{2,2}$");
QRegularExpressionValidator *numberValidator = new QRegularExpressionValidator (numberRegex);
But it is used to check the correct spelling of a phone number. Further in the code, I check the validity of the entered string and then perform the necessary logic.
if(numberValidator->validate(a, b) == QValidator::Acceptable){
...
}
And what can I do? What is a more competent, and most importantly working, solution for creating the correct filling in of a phone number with a mask? In general, without all these "frills" - the mask performs its functions, but insofar as a large number of numbers will need to be entered in the program, managers will not be very happy with the need to aim the mouse at the required place for dialing.
You are calling text() method, according to Qt doc:
When an input mask is set, the text() method returns a modified copy
of the line edit content where all the blank characters have been
removed. The unmodified content can be read using displayText().
So all you should do is finding symbol _ from template and setting cursor to it's position:
if(event->type() == QEvent::MouseButtonPress)
{
int pos = ui->lineEdit_newClientPhone->displayText()
.indexOf("_");
int last_pos = ui->lineEdit_newClientPhone->displayText().length();
ui->lineEdit_newClientPhone->setCursorPosition(
pos == -1 ? last_pos : pos
);
return true;
}
I run into this sometimes as well with the basic widgets. They are great for general purposes, but for special cases or when you really need fast/efficient repeated input like you want, they can be cumbersome. If you've put in a reasonable effort to get the default widgets to behave but still can't, sometimes the easiest way is to just kill it with fire and move on:
class CQLineEditPhoneClickEntry : public QLineEdit
{
Q_OBJECT
public:
explicit CQLineEditPhoneClickEntry( QWidget* pParent = 0 )
: QLineEdit( pParent )
{
setInputMask( "+7\\(999\\)999\\-99\\-99;_" );
}
virtual void mousePressEvent ( QMouseEvent* pEvent ) //override
{
QPoint pressPoint = pEvent->pos();
if( text().count() == 6 )
{
setCursorPosition(4);
return;
}
if( pressPoint.x() > 90 ) // in reality do something less hacky to support high dpi, etc.
{
setCursorPosition(4);
return;
}
QLineEdit::mousePressEvent( pEvent );
}
};
If you have a modern person's healthy aversion to inheritance, then a similar thing can be done using by installing a Qt-style event filter without too much effort. But hopefully this will let you quickly test if this approach works for your needs or otherwise provide another avenue of exploration towards something that does.

GetTextExtentPoint causes aliasing

To whom it may concern,
GetTextExtentPoint and GetTextExtentPoint32 is giving me a bad day.
They are the only method MSDN offers for measuring text but they have two flaws, but nobody else seems to have these problems.
Firstly, they dont take into account newline. They treat the measurement as one long one liner.
Secondly and most importantly, they are causing aliasing when I do DrawText(). I am using ClearType for HFONT but still get aliasing text being drawn.
Kindly let me know precisely what is the problem. Or I might have to create my own measuring text function.
EDIT_________
// note font is created with CLEAR_TYPE_QUALITY
// so it should be antialiased
HFONT createFont(const char *face_name,int height)
{
return CreateFont(height,cHeight,0,0,0,FW_NORMAL,false,false,false,0,0,0,CLEAR_TYPE_QUALITY,0,face_name);
}
RECT box{0,0,640,480);
POINT pos{};
HFONT font = createFont("MyFavouriteFont",30);
HDC canvas = CreateCompatableDC(NULL);
HBITMAP bmp = CreateCompatibleBitmap(NULL,640,480);
SelectBitmap(canvas,bmp);
SelectFont(canvas,font);
SelectBrush(canvas,GetStockObject(DC_BRUSH));
SetDCBrushColor(RGB(255,255,255));
SetBkMode(TRANSPARENT);
SIZE measureText_Msdn(const char *s,HDC font)
{
SIZE sz;
GetTextExtentPoint(font,s,strlen(s),&sz);
return sz;
}
SIZE measureText_Custom(const char *s,HDC font)
{
SIZE sz;
TEXTMETRICSA metrics;
INT char_width, line_width;
// get char height
GetTextMetrics(font,&metrics);
while(*it)
{
if(*it == '\n' || *it == '\r')
{
if(line_width > sz.cx) sz.cx = line_width; // sz.cx stores max width
sz.cy += metrics.tmHeight;
line_width = 0;
}
else
{
GetCharWidth32(font,*it,*it,&char_width);
line_width += char_width;
}
++it;
}
if(line_width > sz.cx) sz.cx = line_width;
if(line_width > 0) sz.cy += metrics.tmHeight; // If there are no chars on this line, the line has no size
return sz;
}
void drawText(HDC dest_ctx)
{
auto s = ,"Text will look blocky";
measureText_Msdn(s,font);
// or measureText_Custom(s,font); will cause font to look blocky and ugly
// If you comment out measureText_* text will be drawn smooth.
FillRect(canvas, &box,(HBRUSH)GetCurrentObject(canvas,OBJ_BRUSH));
DrawTextA(canvas,s,-1,&box,DT_LEFT);
BitBlt(dest_ctx,pos.x,pos.y,box.right,box.bottom,
canvas,0,0,SRCCOPY);
}
SOLUTION_____
I have posted a solution as an answer. I dont like to have to do it. As I said earlier, nobody else seems to have this problem so nobody else would need the solution.
As I said earlier nobody seems to get blocky text when using any of the text measuring functions. I get it when using any of them.
What I noticed is that calling these functions require a context, and the functions seems to be currupting the context. Even if I select a new font into the context I still get blocky text output.
Thus I create a context on the fly and add the desired font into it. And measure with that context, collect the result and delete that context. I tested this and my text are drawn smooth as my original context is unaffected.
Reasons I hate this method:
- I am afraid of the expense of creating and deleting context on the fly.
- I dont think GetTextExtent should currupt my context in the first place.
If you guys have a better way, or know my problem, or why I shouldnt be having this problem kindly post.
EDIT_________
After looking at using keyboard tutorial on MSDN, I saw where the author using a window context instead of memory context for calls to GetTextExtent. It appears that GetTextExtent and the other measurement functions are only meant to be used with window contexts. Which is perfectly fine for me as I dont like Creating Memory Context anyhow.

Highlight some words in PDF using c++ MuPDF

Iam trying to highlight some words inside a PDF, I searched on a good C++ library for doing this, I found MuPDF, I download the last version and compiled it.
Now iam starting to write some codes to highlight the text in the PDF, there is no examples for this task in c++, so I start to try myself.
fz_document *doc;
fz_context *ctx;
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
fz_register_document_handlers(ctx);
doc = fz_open_document(ctx, "D:/b.pdf");
cout << fz_count_pages(ctx, doc) << endl;
fz_page *page = fz_load_page(ctx, doc, 0);
fz_quad *q;
fz_search_page(ctx, page, "more", q, 1);
fz_rect rec = fz_rect_from_quad((*q));
fz_stext_page *pp = fz_new_stext_page(ctx, rec);
fz_point point;
point.x = 0;
point.y = 0;
fz_highlight_selection(ctx, pp, point, point, q, 16);
fz_buffer *buffer = fz_new_buffer_from_stext_page(ctx, pp);
fz_save_buffer(ctx, buffer, "D:/Final.pdf");
That is what i tried so far iam not sure it crash at a point, iam using it with Qt 5.13 MSVC 2017, so what i did wrong, or if some one has a good useful example to do this or for the library in general as it leak examples so far from my search, all the examples are in python, java, and other put for c++ there is few examples just 2 examples coming with the library.
Even if there is another good c++ library has this function please share it.
Thanks in advance.
So it seems you are making the common newbie error of thinking that just because an API uses a pointer, you must declare a pointer. But that is not correct, instead you should declare an object and pass the address of that object. So for example this
fz_quad *q;
fz_search_page(ctx, page, "more", q, 1);
fz_rect rec = fz_rect_from_quad((*q));
should actually be this
fz_quad q; // object not pointer
fz_search_page(ctx, page, "more", &q, 1); // address of the object to get the pointer
fz_rect rec = fz_rect_from_quad(q);
The idea is that fz_search_page will fill in the fz_quad object. Your version fails because you gave an uninitialised pointer to fz_search_page which will result in memory corruption when fz_search_page tries to use that pointer.
You should also definitely add the sanity check
doc = fz_open_document(ctx, "D:/b.pdf");
if (doc == nullptr) // check if we can open the document
{
std::cerr << "cannot open document\n"; // or whatever error handling you prefer
exit(1);
}
Opening files or documents can fail for all sorts of reasons and you should always check that it works.
There's probably lots else that needs improving but those issues stood out for me.
To elaborate on john's answer, you need to allocate space for the results, not just a pointer. This can be stack allocated.
fz_quad q[100]; // stack allocate array of 100 quads
int n = fz_search_page(ctx, page, "more", q, 100);
However, there seem to be some more areas of confusion as to what the APIs actually do.
The fz_search_page function returns a list of quads covering the search hits. fz_highlight_selection also returns a list of quads but this time based on the location on a page a user has dragged using the start and end coordinates of the selection.
fz_new_buffer_from_stext_page returns a plain text version of the structured text data. This is NOT in PDF format.
If you want to add a highlight annotation, then you should create a highlight annotation covering the area you want highlighted:
n = pdf_search_page(ctx, page, "more", q, 100);
if (n > 0) {
pdf_annot *annot = pdf_create_annot(ctx, page, PDF_ANNOT_HIGHLIGHT);
for (i = 0; i < n; ++i)
pdf_add_annot_quad_point(ctx, annot, q[i]);
pdf_update_annot(ctx, annot);
}
Then you can save the new modified PDF document:
pdf_save_document(ctx, doc, "out.pdf", NULL);

WinAPI ComboBox with fixed list of strings and custom data

have a question that has puzzled me several times and I always had to turn to owner-drawn solution - which is, however, what I don't wanna engage with this time. My problem is as the title says and here is a model situation in code:
HWND hComboBox=::CreateWindow(WC_COMBOBOX,NULL,WS_VISIBLE | WS_CHILD | CBS_HASSTRINGS | CBS_DROPDOWN,10,10,100,100,hWnd,0,hInstance,NULL);
ComboBox_SetItemData( hComboBox,
ComboBox_AddString(hComboBox,"My item 1"),
1234
);
ComboBox_SetItemData( hComboBox,
ComboBox_AddString(hComboBox,"My item 2"),
5678
);
int i=ComboBox_FindString(hComboBox,0,1234); // <-- crash
ComboBox_SetCurSel(hComboBox, i );
Apparently, I want to identify each item by its associated custom data (1234 and 5678 in this case). I know I was able to do that in Delphi but haven't yet convinced pure WinAPI to do the same thing (obvious question is what's hidden behind the Delphi's out-of-the-box functionality).
Thanks for a reply.
CBS_HASSTRINGS is meaningless in a non-owner draw combobox. In a non-owner draw combobox, every item has a string and an optional item of data, and ComboBox_FindString always looks for items using a string. Of course, 1234 isn't a valid string pointer. You're basically giving the control an invalid pointer and it's not surprising that it crashes :)
There's no built-in message that lets you search by item data in a non-owner draw combo, so you need to write your own, e.g.:
int iCount = ComboBox_GetCount(hComboBox), iFound = -1;
for (int i = 0; i < iCount; i++)
{
if (ComboBox_GetItemData(hComboBox, i) == 1234)
{
iFound = i;
break;
}
}