Getting all text from Notepad++ document in c++ for Notepad++ plugin - c++

I am writing a plugin for notepad++ with visual studio 2013 (C++).
How can I get all text from notepad++ documantation?
There is a SCI_GETTEXT function for this. I use sendMessage function.(e.g ::SendMessage(curScintilla, SCI_GETTEXT, end, null))
But this function returns long value. Can I convert this long value to char or how can I do this in other way?
SCI_GETTEXT doesn't work without sendMessage funtion.

If I understood correctly their documentation You will have to send the WM_GETTEXT message to the handle of the editor window, where wParam will be the length of text you can accomodate and lParam will be the address of the preallocated data. After SendMessage returns you are suppsoed to have the data populated.
(I am not familiar with the SCI_...stuff , this is the "oldschool" way of solving this problem :) )

Related

GlobalSize function used on Clipboard Data cause error

The first thing I want to say is my English is pretty bad so if my description become a chunk of nonsense text please comment so I can try to clarify my question.
The situation
I'm trying to access clipboard and store all of it's data from all formats possible. I listen to WM_CLIPBOARDUPDATE message then loop through all the format available, get the data for each of the format, get the size then allocate a new memory for them. My googling tell me to use the GlobalSize() function to do that. There the problem arise.
The environment
I am developing a Win32 desktop application using C++ on Visual C++ 2017 version 4.7.02556. I am using Windows 10 64 bits if that matter.
Reproducing the error
Here is my function used to process Windows messages, I remove other message like WM_CREATE or WM_DESTROY because they don't relate to the problem. The consoleOutput() function is used for debugging and they works just fine.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
case WM_CLIPBOARDUPDATE: {
try {
if (OpenClipboard(hWnd)){
UINT uFormat = EnumClipboardFormats(0); // Get the first clipboard format available
HANDLE hContent;
while (uFormat) { //Iterate through all formats
hContent = GetClipboardData(uFormat); // Get the clipboard data of that format
if (hContent) {
SIZE_T size = GlobalSize(hContent); // Get the size of the data I just got
//ERROR
}
uFormat = EnumClipboardFormats(uFormat); // Get the next format
}
}
CloseClipboard();
}
catch (int error) {
CloseClipboard(); // Attempt to close clipboard if thing went wrong
consoleOutput(GetLastError());
throw;
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
The code works fine with everything I tried to copy from text to some random files/directories. But my program gave me an error when I tried to copy a image, for example:
Open an image using MS Paint, select any portion of the image and copy it and the error appears.
Open an image using Picasa, right click and select copy and the error appears.
Press PrntScr button and the error appears.
The error is throwed at SIZE_T size = GlobalSize(hContent); line, and it is either:
Critical error detected c0000374 YClipboard.exe has triggered a breakpoint.
or
Exception thrown at 0x77E17ECC (ntdll.dll) in YClipboard.exe: 0xC0000005: Access violation reading location 0xDD46116F.
The error is not persistent, most of the time it appeared right in the first copy, sometime I can copy the image, but do it multiple times with that same image cause the error. Above all, only attempt to copy "image" data cause the problem.
What I have tried so far
I am a novice about developing desktop app, and I my searching don't find the problem anywhere else. When I peek at the clipboard data using a third-party app, I found out the error only appear when my program met the CF_BITMAP or CF_METAFILEPICT format, and (not so) coincidentally both of those formats have a memory of size 0. Still I am unable to fix my problem.
What I need
Someone please enlighten me about this problem: what is the problem, the cause of it, how to fix it or just a suggestion about another method that help me read the size of clipboard data to replace GlobalSize() function.
Thanks in advance.
Not all clipboard formats present an HGLOBAL that you can use with functions like GlobalSize().
For example, CF_BITMAP presents a handle to a bitmap; an HBITMAP that you can use with functions like GetObject().
You'll need to handle those formats specially. See the Standard Clipboard Formats list on MSDN for more information.

SendMessage to TextBox Window Child in C++ not working

char arbc[60];
cout << "Message: ";
cin.getline(arbc+'\0',sizeof(arbc)+1);
system("pause");
PostMessage(hwndch,WM_SETTEXT,(WPARAM)*arbc,0);
So hwndch is a window child and the child is a textbox, it's parent is the main window form. The problem is that WM_SETTEXT isn't setting the text of the textbox to the string of characters. I know it's not a problem with the windowchild because WM_CHAR outputs at least 1 character in the textbox.
Note: I'm modifying the handles of another process.
You cannot use PostMessage with WM_SETTEXT. That's a synchronous message. Your problem is even greater when the window is in a different process. The system needs to marshal the text from your process into another process. It cannot do that with an asynchronous message.
Use SendMessage instead.
Your other problems include at least the following:
The wParam argument is wrong. That parameter is ignored. Pass (LPARAM)arbc to lParam instead. The documentation is quite clear.
You should not use C strings in any case. Use std::string, and then c_str().
Your use of sizeof is wrong. Your use of getline is all wrong too.
You seem confused over which function you are calling. The title says SendMessage, the code says PostMessage.
You probably want something along these lines:
std::cout << "Message: ";
std::string msg;
std::getline(std::cin, msg);
SendMessage(hwndch, WM_SETTEXT, 0, (LPARAM)msg.c_str());

Obtaining the virtual key code from a WM_CHAR message

I am getting text input and keypress input from the WM_CHAR and WM_KEYDOWN messages
What I want to do is filter out WM_CHAR messages the have the same VK_ code as the key that is bound to enable the control that you enter text in.
EG: Game uses ~ to enable console, key binding is done via VK_OEM3 and WM_KEYDOWN, but text input into the console needs text from WM_CHAR.
As the WM_KEYDOWN happens first, the console is activated, then a WM_CHAR of ~ is sent to the console buffer which I don't want.
I figured the best way to prevent this is to compare the VK_ from the WM_CHAR to the bound key for the control and filter it out.
Is there a way to get the VK_ from a WM_CHAR message?
I read that you can get the scancode out of Lparam at bits 16-23
But am unsure how to:
Extract the value of the scancode from lparam
Translate the scan code to a VK_ correctly
After some messing around I managed to extract the virtual key with the following code:
This code gets the address of lParam as a unsigned char array (one byte of length), then uses pointer arithmatic to address the 3rd byte (bits 16-23):
unsigned char scancode = ((unsigned char*)&lParam)[2];
This code translates from the scancode to the virtual key:
unsigned int virtualKey = MapVirtualKey(scancode,MAPVK_VSC_TO_VK);
Perhaps you migh use MapVirtualKey.
I am not sure how to extract scancode from lparam as documentation does not state that - either get entire lparam and count that this function knows which bits to look at, or use bitfield struct and just get right bits out of it. I think on of those methods should work - trying both shouldn't be difficult.

Get text using SendMessage() C++

I am trying to get text from a textbox in a specific window. For this I'm using SendMessage Api function, I dont know if this is the corect way:
SendMessage(hwnd, WM_GETTEXT, 0, 0);
But I dont know how to print the text. For the argument 3 and 4 in msdn site it says: Additional message-specific information. So i dont know if I need to pass something else beside 0. I tried this also:
SendMessage(hwnd, WM_GETTEXT, sizeof(text), LPARAM(text));
But it prints the name of the textbox, I need to retrieve the text inside the box?
How can I do this? Is SendMessage() the correct API function to use ?
Thank you.
edit:
I omit to say, I am enumerating the child windows from a window, and for me it looks like a textbox, where you have to type a name. I am retrieving the username of a Instant messaging window so I cant compare it to a string, is that a textbox ?
You should use GetWindowText. More information here.
Read the MSDN documentation again. It does NOT say "Additional message-specific information" for those parameters:
wParam The maximum number of
characters to be copied, including the
terminating null character.
ANSI applications may have the string
in the buffer reduced in size (to a
minimum of half that of the wParam
value) due to conversion from ANSI to
Unicode.
lParam A pointer to the buffer that
is to receive the text.
This code works for local only:
char *szText;
szText = (char *)GlobalAlloc(GPTR, 255);
SendMessage(hEditControl, WM_GETTEXT, 255, (LPARAM)szText);
MessageBox(hWnd, szText, "It's your message", MB_OK | MB_TOPMOST);
GlobalFree((HGLOBAL)szText);

How to print many format strings into window?

After successfully solve this problem how to print a format string into window, another problem comes to me.
If there are many format strings, how to print them into window? For example below:
sprintf(buf, formatString-1...);
SendMessage(hwnd, WM_SETTEXT, NULL, (LPARAM)buf);
...
sprintf(buf, formatString-2...);
SendMessage(hwnd, WM_SETTEXT, NULL, (LPARAM)buf);
...
sprintf(buf, formatString-3...);
SendMessage(hwnd, WM_SETTEXT, NULL, (LPARAM)buf);
...
Notice that only formatString-3 is printed into window, while i want to put them all into window. How to do this?(PS: Please Do not use buf concatenate) Thank you!~
Are you trying to produce a console-style or log-style window, with multiple lines of text, one after the other?
If so, simplest approach is to pick a control that will do this for you. Something like a static (usually used for labels) typically is only useful for one string at a time. If you want to display more than one line of output, your two main options are:
Listbox control: add items to the end using LB_ADDSTRING. (You may want to follow that with LB_SETCURSEL or similar to select the last item, so that as items are added to the end, it will scroll to show the last item.)
Read-only Multi-line Edit control: append text to the end using the technique outlined here on MSDN. Note that with this approach, you need to supply the "\r\n" yourself to create a new line.
Each WM_SETTEXT message overwrites the previous one. That's why you only observe the effects of the final message.
Although you state that you don't want to concatenate the buffer before sending the WM_SETTEXT message, that's the only option with WM_SETTEXT.
If you have an edit control then you can insert text using the EM_REPLACESEL message.