SetLimitText not working for multiline in MFC application - visual-c++

I have an edit text control which is represented as following in .rc:
EDITTEXT IDC_EDIT1, 26, 23, 60, 14, ES_RIGHT | ES_MULTILINE | ES_AUTOHSCROLL
I tried un-restrict the limit lext using: m_editCtrl.SetLimitText(0);
but it is not working. If I remove 'ES_RIGHT' from the rc file, it worked well.
Is there any way to to un-restrict the text limit for ES_RIGHT?
Thanks in advance.

if(m_pEdit != NULL)
{
CString strVal;
//Get text value from the dit control
m_pEdit->GetWindowText(strVal);
//Get parent control
CWnd* pParentHwnd = m_pEdit->GetParent();
CRect ctrlRect;
m_pEdit->GetWindowRect(&ctrlRect);
pParentHwnd->ScreenToClient(&ctrlRect);
DWORD dwStyle = m_pEdit->GetStyle();
DWORD dwExstyle = m_pEdit->GetExStyle();
CFont* pFont = m_pEdit->GetFont();
int nCtrlID = m_pEdit->GetDlgCtrlID();
DWORD dwSelection = m_pEdit->GetSel();
CWnd* pWndPreviousCtrl = m_pEdit->GetNextWindow(GW_HWNDPREV);
m_pEdit->DestroyWindow();
if (dwStyle & ES_MULTILINE)
{
dwStyle &= ~ES_MULTILINE;
}
//Create edit control
BOOL bIsCreated = m_pEdit->CreateEx(dwExstyle, _T("EDIT"), strVal, dwStyle, ctrlRect, pParentHwnd, nCtrlID);
if (bIsCreated)
{
//Set window position to maintain z-order for tab navigation
m_pEdit->SetWindowPos(pWndPreviousCtrl, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
//Restore font
m_pEdit->SetFont(pFont);
//Restore last selection
m_pEdit->SetSel(dwSelection);
if (bHasFocus)
{
m_pEdit->SetFocus();
}
}
}

It appears that ES_RIGHT style doesn't play nice with ES_AUTOHSCROLL.
Looks like you can make it work if you create your edit control without ES_RIGHT style and later modify it like that:
GetDlgItem(IDC_EDIT1)->ModifyStyle(0, ES_RIGHT);

The issue is reproducible for ES_MULTILINE. Remove multiline from rc, it will solve the problem.

Related

zoom in / out the image inside a pictureBox in VC++2015 (OpenCV used)

OS : Win 10
IDE: Visual Studio 2015
Language: C++
Others: I use OpenCV 3.4
I just create a Window Form using CLR empty project,
then put on a pictureBox & three buttons.
First button: load a local image and show on the pictureBox:
pictureBox1->Image = Image::FromFile("D:/something.png");
global_mat = imread("D:/something.png", 1); // global_mat is a global Mat.
zoom_in_counter = 0; // zoom_in_counter is a global int.
Second button: zoom in the image in the pictureBox
if (zoom_in_counter < 5) // You can only enlarge the image 5 times.
{
Mat new_mat = Mat::zeros(0, 0, CV_8UC3);
resize(global_mat, new_mat, cv::Size(global_mat.cols * 2, global_mat.rows * 2));
global_mat = new_mat;
if ((pictureBox1->Width != new_mat.cols) || (pictureBox1->Height != new_mat.rows))
{
pictureBox1->Width = new_mat.cols;
pictureBox1->Height = new_mat.rows;
pictureBox1->Image = gcnew System::Drawing::Bitmap(new_mat.cols, new_mat.rows);
}
System::Drawing::Bitmap^ bmpImage = gcnew Bitmap(
new_mat.cols, new_mat.rows, new_mat.step,
System::Drawing::Imaging::PixelFormat::Format24bppRgb,
System::IntPtr(new_mat.data)
);
Graphics^ g = Graphics::FromImage(pictureBox1->Image);
g->DrawImage(bmpImage, 0, 0, new_mat.cols, new_mat.rows);
pictureBox1->Refresh();
delete g;
zoom_in_counter++;
}
Third buttin: zoom out the image in the pictureBox
if (zoom_in_counter > 0) // You can't shrink the image.
{
Mat new_mat = Mat::zeros(0, 0, CV_8UC3);
resize(global_mat, new_mat, cv::Size(global_mat.cols * 0.5, global_mat.rows * 0.5));
global_mat = new_mat;
if ((pictureBox1->Width != new_mat.cols) || (pictureBox1->Height != new_mat.rows))
{
pictureBox1->Width = new_mat.cols;
pictureBox1->Height = new_mat.rows;
pictureBox1->Image = gcnew System::Drawing::Bitmap(new_mat.cols, new_mat.rows);
}
System::Drawing::Bitmap^ bmpImage = gcnew Bitmap(
new_mat.cols, new_mat.rows, new_mat.step,
System::Drawing::Imaging::PixelFormat::Format24bppRgb,
System::IntPtr(new_mat.data)
);
Graphics^ g = Graphics::FromImage(pictureBox1->Image);
g->DrawImage(bmpImage, 0, 0, new_mat.cols, new_mat.rows);
pictureBox1->Refresh();
delete g;
zoom_in_counter--;
}
And then,
every I zoom in or zoom out, it works,
excludeingthe image is zoomed back to the original size.
I'll get such error message:
An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
It's really odd!
Finally, my friend figure out what's wrong,
please refer to:
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms536315(v=vs.85).aspx
stride [in]
Type: INT
Integer that specifies the byte offset between the beginning of one scan line and the next. This is usually (but not necessarily) the number of bytes in the pixel format (for example, 2 for 16 bits per pixel) multiplied by the width of the bitmap. The value passed to this parameter must be a multiple of four.

User input displayed at wrong coordinates in OpenCV

I'm trying to display circles at a user accepted input (usually centers), using OpenCV 2.4.3 (VS 2010). On output image (displayed using 'namedWindow') circle seems to shift column-wise as one marks points along columns. Not sure how I should correct this.
Code:
struct OPTIONS{
OPTIONS(): X(-1), Y(-1), drawing_dot(false){}
int X;
int Y;
bool drawing_dot;
};
OPTIONS options;
void my_mouse_callback( int event, int x, int y, int flags, void* param ){
IplImage* image = (IplImage*) param;
switch( event ){
case CV_EVENT_LBUTTONDOWN:
options.X = x;
options.Y = y;
options.drawing_dot = true;
break;
default:
break;
}
}
int main( void ){
IplImage* image = cvLoadImage("Images/TestRealData/img1.bmp");
Mat frame = imread("Images/TestRealData/img1.bmp");
namedWindow("Test", CV_WINDOW_KEEPRATIO);
cvSetMouseCallback("Test", my_mouse_callback, (void*) image);
while( cvWaitKey(15) != 27 ){
if( options.drawing_dot ){
circle(frame, Point(options.X,options.Y), 3, CV_RGB(0,0,255), 2);
options.drawing_dot = false;
}
imshow("Test", frame);
waitKey(10);
}
cvReleaseImage(&image);
return 0;
}
I think the circle does not shift. The mouse cursor may trick our eyes. You may simply check it by increasing the radius and reduce the thickness of the circle outline like:
circle(frame, Point(options.X, options.Y/2), 15, CV_RGB(0, 0, 255), 1);
By the way, I think if you want to draw the circle at the point you click on, options.Y should not be divided by 2.
Found answer after much time lost - Make sure to specify flags in 'namedWindow'. Changing flag to CV_WINDOW_KEEPRATIO did the trick for me. Hope this helps somebody out there.

How to scale font when the font-face is having only one font-size using MFC's DrawText

.
void CMainWindow::OnPaint()
{
CPaintDC DC(this);
//CRect rc(5, 5, 191, 99);
CRect rc(1, 1, 38, 19);
CBrush brush(DC.GetBkColor());
CBrush* pOldBrush = DC.SelectObject(&brush);
DC.FillRect(&rc, &brush);
DC.SelectObject(pOldBrush);
DC.SetBkMode(TRANSPARENT);
LOGFONT LogFont;
LogFont.lfHeight = -13;
LogFont.lfWidth = 0;
LogFont.lfEscapement = 0;
LogFont.lfOrientation = 0;
LogFont.lfWeight = 400;
LogFont.lfItalic = 0;
LogFont.lfUnderline = 0;
LogFont.lfStrikeOut = 0;
LogFont.lfCharSet = 0;
LogFont.lfOutPrecision = 0;
LogFont.lfClipPrecision = 0;
LogFont.lfQuality = 0;
LogFont.lfPitchAndFamily = 0;
wcscpy_s(LogFont.lfFaceName, _T("System"));
//float OffSetY = 1.0;
//float OffSetX = 1.0;
float OffSetY = 0.2;
float OffSetX = 0.2;
LogFont.lfHeight = (int)(LogFont.lfHeight * OffSetY);
LogFont.lfWidth = (int)(LogFont.lfWidth * OffSetX);
CFont* pFont = new CFont;
pFont->CreateFontIndirect(&LogFont);
CFont* pOldFont = DC.SelectObject( pFont );
CString sTemp(_T("Title current_folder\r\nField1\r\nComment:\r\nControl #:\r\nDescription:\r\nMagnification:\r\n"));
sTemp.Replace(_T("&"), _T("&&"));
int alignment = 0;
switch(alignment)
{
case 1:
DC.DrawText(sTemp, -1, rc, DT_WORDBREAK | DT_RIGHT | DT_EDITCONTROL);
break;
case 2:
DC.DrawText(sTemp, -1, rc, DT_WORDBREAK | DT_CENTER | DT_EDITCONTROL);
break;
default:
DC.DrawText(sTemp, -1, rc, DT_WORDBREAK | DT_EDITCONTROL);
break;
}
DC.SelectObject( pOldFont );
delete pFont;
}
When using System or FixedSys font (which have only one font size 10 and 9 resp) then in the text drawn is perfect in case when OffSetX and OffSetY is 1 and rc(5, 5, 191, 99). But If I change the OffSetX and OffSetY to 0.2 and rc(1, 1, 38, 19) then the text if truncated from bottom-right. This is case only when using the mentioned font which is having just one font-size and for other font is working fine and text drawn is properly scaled.
Since the font is having one font-size so DrawText is using this font size in all cases and rect given is too small to accommodate this text so it is showing only the few characters.
Is there any way I can fixed it, so that the text get scaled at these zoom conditions. This is the behavior I am getting in one of MFC Project when I perform zoom-in operation at the scenario mentioned above.
Any suggestion or alternative for this will be very helpful and appreciable.
Thanks.
Don't hard-code your font size like that! Instead, perform necessary calculations:
const int SIZE_IN_POINTS = 12;
LogFont.lfHeight = -MulDiv(SIZE_IN_POINTS, DC.GetDeviceCaps(LOGPIXELSY), 72);

CEdit index at which line-break happens

I am getting text from CEdit control. I need to imitate the same text on image. The edit control is multiline, so when I keep on typing long string the remaining part of the word goes to the next line.
I am not getting at which text index in the CEdit the character goes on the next line.
So while trying to do this, I am able to insert "\r\n" if the width of line exceed the width of the rect. But the problem is if the alignment is center the the character after the inserted "\r\n" is treated as new word by the DrawText api and purpose of the above insertion of new-line character fails.
Can someone let me know, Is there some way I can know where the line is breaking in CEdit or alternative for the same.
CString strTempFormattedText(_T(""));
LONG tempTotalWidth = 0;
for(int i = 0; i < myText.GetLength(); i++) {
TCHAR tempChar = myText.GetAt(i);
tempTotalWidth += pDC->GetTextExtent(CString(tempChar), 1).cx;
if(tempTotalWidth >= rc.Width()) {
tempTotalWidth = 0;
strTempFormattedText.Append(_T("\n\r"));
}
strTempFormattedText.AppendChar(tempChar);
}
myText = strTempFormattedText;
switch(ALIGNMENT)
{
case RIGHT:
pDC->DrawText(myText, -1, rc, DT_WORDBREAK | DT_RIGHT );
break;
case CENTER:
pDC->DrawText(myText, -1, rc, DT_WORDBREAK | DT_CENTER);
break;
case LEFT:
pDC->DrawText(myText, -1, rc, DT_WORDBREAK | DT_LEFT);
break;
}
Thanks
I think you should combine LineIndex, LineLength and PosFromChar to solve your problem. Using the API instead of the data could be useful if you will need access the more complex CRichEditText.

create native bitmap library

I am Persian and j2me do not have good support for persian font.
I will create a native font library that get bitmap font and paint my persian text in desplay. But I have a problem.
In english each letter is a set consist shap and uncode. Like (a , U+0061)
But in persian a char may have several shape. for example letter 'ب' in persian alphabet can be:
آب --when it is separate letter in a word
به --when it is start letter in a word
...
How can I get other form of a letter from font file?
I am a persian developer and I had the same problem in about 4 years ago.You have some way to solve this problem:
1-using custom fonts.
2-reshape your text before display it.
A good article in about first,is "MIDP Terminal Emulation, Part 3: Custom Fonts for MIDP ".But for arabic letters I think that is not simple.
In about second way,say you would to replace any character in your text with correct character.This means when you have:
String str = "به";
If get str characters they will be look like:
{1576,1607} that is like "ب ه" instead of "به".So you would to replace incorrect Unicode with correct Unicode codes(in this case correct characters are: {65169, 65258}).You can use "Arabic Reshapers" even reshapers that designed for android!I saw 2 link for this reshapers:1-github 2-Arabic Android(I'm persian developer and so I do not try them,instead I create classes with the same idea as they have).
With using a good reshaper also you may have problem with character arranging from left to right instead of right to left.(some phones draw characters from left to right and other from right to left).I use below class to detect that ordering is true(from right to left) or not:
public class DetectOrdering{
public static boolean hasTrueOrdering()
{
boolean b = false;
try {
char[] chArr = {65169, 65258};
String str = new String(chArr);
System.out.println(str);
int width = f1.charWidth(chArr[1]) / 2;
int height = f1.getHeight();
image1 = Image.createImage(width, height);
image2 = Image.createImage(width, height);
Graphics g1 = image1.getGraphics();
Graphics g2 = image2.getGraphics();
g1.drawString(str, 0, 0, 0);
g2.drawChar(chArr[1], 0, 0, 0);
int[] im1 = new int[width * height];
int[] im2 = new int[width * height];
image1.getRGB(im1, 0, width, 0, 0, width, height);
image2.getRGB(im2, 0, width, 0, 0, width, height);
if (areEqualIntArrrays(im1, im2)) {
b = true;
} else {
b = false;
}
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
private static boolean areEqualIntArrrays(int[] i1, int[] i2) {
if (i1.length != i2.length) {
return false;
} else {
for (int i = 0; i < i1.length; i++) {
if (i1[i] != i2[i]) {
return false;
}
}
}
return true;
}
}
If DetectOrdering.hasTrueOrdering() returns true,sure that phone draw Arabic characters from right to left and display your String.If returns false it draws from left to right.If phone draws Arabic character from left to right you would to reverse string after reshape it and then you can display it.
You can use one alphabet.png for the direct unicode mappings (those where the persian char does not change because of the neighbor chars). If your characters are monospaced, you may start with below class, as seen at http://smallandadaptive.blogspot.com.br/2008/12/custom-monospaced-font.html:
public class MonospacedFont {
private Image image;
private char firstChar;
private int numChars;
private int charWidth;
public MonospacedFont(Image image, char firstChar, int numChars) {
if (image == null) {
throw new IllegalArgumentException("image == null");
}
// the first visible Unicode character is '!' (value 33)
if (firstChar <= 33) {
throw new IllegalArgumentException("firstChar <= 33");
}
// there must be at lease one character on the image
if (numChars <= 0) {
throw new IllegalArgumentException("numChars <= 0");
}
this.image = image;
this.firstChar = firstChar;
this.numChars = numChars;
this.charWidth = image.getWidth() / this.numChars;
}
public void drawString(Graphics g, String text, int x, int y) {
// store current Graphics clip area to restore later
int clipX = g.getClipX();
int clipY = g.getClipY();
int clipWidth = g.getClipWidth();
int clipHeight = g.getClipHeight();
char[] chars = text.toCharArray();
for (int i = 0; i < chars.length; i++) {
int charIndex = chars[i] - this.firstChar;
// current char exists on the image
if (charIndex >= 0 && charIndex <= this.numChars) {
g.setClip(x, y, this.charWidth, this.image.getHeight());
g.drawImage(image, x - (charIndex * this.charWidth), y,
Graphics.TOP | Graphics.LEFT);
x += this.charWidth;
}
}
// restore initial clip area
g.setClip(clipX, clipY, clipWidth, clipHeight);
}
}
And change it to use a different char_uxxxx.png file for each persian char that changes because of the neighbor chars.
When parsing your string, before painting, you must check which png file is appropriate to use. Hope this is a good place to start.

Resources