C++ WINAPI Button Clipboard - Copy action - c++

I am a bit new to C++ but I know the basics and how to use it properly. I am just wondering how to copy to a clipboard in a windows application. I want 4 buttons to be able to copy a message when clicked and store it in clipboard. Here is the code for the button, the if statement is the action that is carried out when clicked:
case WM_CREATE:{
CreateWindow(TEXT("BUTTON"), TEXT("Copythistext"),
WS_CHILD | WS_VISIBLE,
12,60,10,20,
hwnd, (HMENU) ID_BUTTON, NULL, NULL
);
break;
}
case WM_COMMAND:{ //this is where the button performs it's task
if(LOWORD(wParam)== ID_BUTTON) {
//this is where the task goes
}
break;
}

Sequence of events:
void AddToClipboard(char* pszText)
{
int nStrLen = strlen(pszText);
HGLOBAL hMem = GlobalAlloc(nStrLen + 1, GMEM_SHARE);
char* pCopyTo = (char*) GlobalLock(hMem);
strcpy(pCopyTo, pszText);
GlobalUnlock(hMem);
OpenClipboard(NULL); // or HWND handle instead of NULL
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem); // hMem is handle to memory allocated with GlobalAlloc
CloseClipboard();
}
For the hMem, you usually do a GlobalAlloc(), GlobalLock(), copy string to the pointer returned by GlobalLock(), then do a GlobalUnlock() on the handle

There is a curious way to send text from BUTTON to clipboard: via SetDlgItemText + WM_LBUTTONDBLCLK to STATIC with SS_NOTIFY (size of STATIC may be =0).

Related

Remove focus from SAVE button in OPENFILENAME win32?

Problem:
If the user holds the "enter" keyboard button and opens OPENFILENAME Save As Dialog, it will automatically save the file - dialog only blinks.
Desired result:
The user holds the "enter" keyboard button, opens OPENFILENAME Save As Dialog, nothing happens. He needs to click on the Save button or click again the "enter" keyboard button to save a file.
My current code:
OPENFILENAME ofn;
TCHAR szFile[260] = { 't','e','s','t'}; // example filename
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
//Files like: (ALL - *.*), (Text - .TXT)
ofn.lpstrFilter = _T("All\0*.*\0Text\0*.TXT\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetSaveFileName(&ofn) == TRUE)
{
// file saved
}
Possible solution:
When ofn.lpstrFile is empty do nothing; Can't save file when there
is no filename
When ofn.lpstrFile has suggested filename then turn off focus on "Save" button or somehow ignore button enter holding.
I was trying to do that but failed, I am a beginner in CPP :(
Thanks for help
The easy solution to prevent data loss is to add the OFN_OVERWRITEPROMPT flag. This does not prevent the issue from happening if the suggested name does not already exist as a file.
To actually interact with the dialog you need OFN_ENABLEHOOK and a hook function. When you receive WM_NOTIFY, you can handle CDN_FILEOK to block the suggested name if not enough time has passed or maybe it is possible to change the focus in CDN_INITDONE.
Either way, you have to be mindful of the fact that you are changing how a common dialog works and this might anger some users.
Here is one way to do it. The actual delay to return the dialog to normal is something you have to decide for yourself.
const int btnid = 1337;
void CALLBACK resetsavedlgdefpush(HWND hWnd, UINT Msg, UINT_PTR idEvent, DWORD Time)
{
KillTimer(hWnd, idEvent);
HWND hDlg = GetParent(hWnd);
UINT id = LOWORD(SendMessage(hDlg, DM_GETDEFID, 0, 0));
if (id == btnid)
{
SendMessage(hDlg, DM_SETDEFID, IDOK, 0);
}
}
UINT_PTR CALLBACK mysavehook(HWND hWndInner, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == WM_NOTIFY)
{
OFNOTIFY*pOFN = (OFNOTIFY*) lParam;
if (pOFN->hdr.code == CDN_INITDONE)
{
HWND hDlg = GetParent(hWndInner);
CreateWindowEx(0, TEXT("BUTTON"), 0, BS_DEFPUSHBUTTON|BS_TEXT|WS_CHILD|WS_VISIBLE, 0, 0, 0, 0, hWndInner, (HMENU) btnid, 0, 0);
SendMessage(hDlg, DM_SETDEFID, btnid, 0);
PostMessage(hDlg, DM_SETDEFID, btnid, 0);
int keydelay = 0;
SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &keydelay, 0);
SetTimer(hWndInner, 0, (250 * ++keydelay) * 5, resetsavedlgdefpush);
}
}
return 0;
}
...
ofn.Flags = OFN_PATHMUSTEXIST|OFN_EXPLORER|OFN_OVERWRITEPROMPT|OFN_ENABLESIZING|OFN_ENABLEHOOK;
ofn.lpfnHook = mysavehook;
MessageBox(ofn.hwndOwner, TEXT("Hold enter to test..."), 0, 0);
if (GetSaveFileName(&ofn) == TRUE) ...

C++ win32 How do I make a password field selectable and enable copying and pasting?

So I'm currently in need of a password field, for displaying already known password. But since I don't want to directly show the password to the user, I have decided to use a password field instead of a normal field. Since the program itself is working I will only show the code where I create the edit field, since that's the only place I will make changes to it based on the requirements of this program.
This is the code snippet of my edit box
std::wstring password = account.GetPassW();
HWND hWndEditPassword = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("Edit"),
password.c_str(), WS_CHILD | WS_VISIBLE | ES_PASSWORD, 85, 30, 245,
20, hWnd, NULL, NULL, NULL
);
account is a variable of type struct UserAccount and GetPassW() is a function which converts from std::string to std::wstring since the strings are originally loaded and stored as those first ones.
This code works fine if it was a normal login form, but this is not a login form, this is a login recovery form, where the password field shows asterisks (*) for security reasons. And this password field has to be support selecting with Ctrl + A and copy pasting with Ctrl + C and Ctrl + V which doesn't seem to be the case with the default password field with this setting.
Again like I said. This is not a program for logging in to something. This is a program where you select a platform or similar, and this window pops up with your stored username and password, already filled into the input boxes, ready to be copy pasted into respective program. The problem is since I'm using ES_PASSWORD for the password box, it automatically makes the edit box unable to select and copy which would not work with the intention of this program. So I need to find a way to enable those features of an edit box while keeping the asterisk stuff.
How would I get along doing this?
Would really appreciate some code to illustrate the solution.
So I managed so solve the problem. But the solution is more of a patch job than a direct solution, so I wouldn't say this answer would help other but it worked for me for what I intend to use it for.
So what I did was to keep it a password field, but I made a static variable
static WNDPROC wndProcPasswordOld;
static UserAccount currentAccount;
static HWND hWndEditPassword;
Then where I initialize the password box, I now have this
hWndEditPassword = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("Edit"), password.c_str(),
WS_CHILD | WS_VISIBLE | ES_PASSWORD | ES_READONLY, 85, 30, 245,
20, hWnd, NULL, NULL, NULL);
wndProcPasswordOld = (WNDPROC)SetWindowLongPtr(hWndEditPassword, GWLP_WNDPROC,
(LONG_PTR)WndProcPassword);
// This is further down
currentAccount = account;
Then I have a WNDPROC named WndProcPassword forward declared and implemented at the bottom as follows
LRESULT CALLBACK WndProcPassword(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_KEYDOWN:
if ((wParam == 'C' || wParam == 'c') && GetKeyState(VK_CONTROL) & 0x8000)
{
std::string data = currentAccount.password;
const char *output = data.c_str();
const size_t len = strlen(output) + 1;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), output, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
break;
}
return CallWindowProc(wndProcPasswordOld, hWnd, message, wParam, lParam);
break;
default:
return CallWindowProc(wndProcPasswordOld, hWnd, message, wParam, lParam);
}
return 0;
}
This does however not remove the sound, but it's not big of a deal with how I intend using this program, but I decided to leave this answer since I couldn't find any other information on how to have an edit field copyable while still having the characters show asterisks.
EDIT:
I have now found a solution I find better than the above but I've decided to keep both.
The WM_KEYDOWN event in WndProcPassword has changed to WM_KEYUP.
Additionall in the if statement inside WM_KEYUP I'm also checking if the event is
if (((wParam == 'C' || wParam == 'c') && GetKeyState(VK_CONTROL) & 0x8000) || (wParam == VK_CONTROL && (GetKeyState('C') & 0x8000 || GetKeyState('c') & 0x8000)))
{
// copy to clipboard
}
I then went ahead and changed the creation of the box to
hWndEditPassword = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("Edit"), L"",
WS_CHILD | WS_VISIBLE | ES_READONLY, 85, 30, 245,
20, hWnd, NULL, NULL, NULL);
SetEditText(password);
Where this SetEditText looks as follows
void SetEditText(std::wstring text)
{
int buffersize = text.length() + 1;
WCHAR *wchars = new WCHAR[buffersize];
memset(wchars, 0, sizeof(WCHAR) * buffersize);
for (int i = 0; i < text.length(); i++)
wchars[i] = L'*';
SetWindowText(hWndEditPassword, wchars);
delete[] wchars;
}
This change makes the control act as a normal edit box, only change is that when you set the text, you replace the input with asterisks manually, and since copying is done on key down, you simply add your own copying in the keyup event.
This also removes all limitations and error sounds when interacting with the input box.

Strange GetWindowText(); error

I am trying to get the text of a textedit control in a dialog in my Win32 C++ Application.
I am using the following block of code to get that, and also to test it.
HWND hCarRegNo = GetDlgItem( hDlg, IDC_REGNUMBER );
if( hCarRegNo )
{
LPWSTR carRegNo = NULL;
GetWindowText(hCarRegNo, carRegNo, 20);
MessageBox(hDlg, carRegNo, _T("Test"), MB_OK);
}
The MessageBox output is an empty string.
Where is my mistake?
Not allocating any memory for carRegNo. Try this
WCHAR carRegNo[20];
GetWindowText(hCarRegNo, carRegNo, 20);
After some more research, I have solved the problem: instead of LPWSTR, I had to use TCHAR carRegNo[256] to make this work.
HWND hCarRegNo = GetDlgItem( hDlg, IDC_REGNUMBER );
if( hCarRegNo )
{
TCHAR carRegNo[256] = L"";
GetWindowText(hCarRegNo, carRegNo, 256);
MessageBox(hDlg, carRegNo, _T("Test"), MB_OK);
}

Null handle error

I am working on a Win32++ application that has a listview in the main window. This is my code:
HWND CarsListView = NULL;
switch (message)
{
case WM_SHOWWINDOW:
CarsListView = CreateListView(hWnd);
ShowWindow(CarsListView, SW_SHOW);
break;
case WM_SIZING:
{
if(!CarsListView)
MessageBox(hWnd, _T("Null handle."), _T("Error"), MB_ICONERROR | MB_OK);
RECT WindowRect;
GetWindowRect( hWnd, &WindowRect);
SetWindowPos(CarsListView, NULL, 0, 0, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, SWP_SHOWWINDOW);
}
break;
// ...
}
and the CreateListView definition is this:
HWND CreateListView (HWND hwndParent)
{
INITCOMMONCONTROLSEX icex; // Structure for control initialization.
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
RECT rcClient; // The parent window's client area.
GetClientRect (hwndParent, &rcClient);
// Create the list-view window in report view with label editing enabled.
HWND hWndListView = CreateWindow(WC_LISTVIEW,
L"",
WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
0, 0,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
hwndParent,
/*(HMENU)*/NULL,
hInst,
NULL);
return (hWndListView);
}
When the window receives WM_SIZING, I get that CarsListView = NULL
What can I do to have that handle pointing to my listview?
Three way to do that kind of stuff.
The Ugly
Store your CarsListView HWND in a static. You can't have 2 instance of the parent windows.
The Bad
Use SetWindowsLongPtr(parentHWND,GWLP_USERDATA,CarsListViewHWND) in your init and GetWindowLongPtr when needed. It's fast you can have as many instance as you want, but if you need more than one information I recommend storing a struct with your HWND inside instead of single HWND for future extensibility.
The Good ?
Use SetProp(parentHWND,"Your Unique String",hDataHandle); its by far the more code but with that usage you can use it on every windows without caring if the USERDATA is already used or not. It's the best approach when you need to add personal property to a windows/code you can't be sure how it will be used or change over time
There are two ways to do this: The "good" way and the "bad" way.
The "bad" way is to simply declare the local variable as static, however it means you can't create two windows of this type in the same process.
The "good" way is to memorize it in a heap-allocated structure, and store a pointer to this structure in the Window information using SetWindowLongPtr(). You can then retrieve this structure with GetWindowLongPtr().
I would create the listview in WM_CREATE and not in WM_SHOWWINDOW. Also make the handle either global or static.
Or you can also create the list view globally and keep it hidden and just make it visible and set its position whenever you want it to do.

Load an animated cursor at runtime from memory

I want to load an animated cursor stored in .ani format, which is described to be a RIFF archive/container, from memory without writing the memory to a temporary file. Thus far I am able to parse the .ani file structure and load the individual frames as a normal icon with the aid of CreateIconFromResourceEx LookupIconIdFromDirectoryEx
One of the problems that proofs difficult is the actual composition of these frames and the animation data (jiffy-rate etc) as there appears to be no entries in the Windows API to do so. Documentation or written knowledge over the subject seems to be limited to loading non-animated icons/cursors from memory.
Similar questions such as 'Load an embedded animated Cursor from the Resource' express the desire to load an animated cursor from an embeddable resource. However i am not able to reproduce a workable solution from that either. Partly because the resource compiler in visual studio 2008 & 2010 doesn't support .ani (only ico and cur) files and therefor embedding it simply results in a 1:1 copy of the bytes as they were in the original file as opposed to .cur and .ico files which get decomposed into multiple resources. The subsequent call to CreateIconFromResource as shown in both answers does not work because the data it expects is the icon/cursor data of a single directive in a icon archive and not a RIFF-based file structure.
To summarize I'm interested in any information regarding the structures of animated cursors (in memory) or otherwise relevant pointers that could assist me in pursuing my goal.
After re-evaluating loading an animated cursor from an embeddable resource as pointed out by mfc I have found a solution that allows me to load the cursors from an arbitrary memory address.
Data from an embeddable resource and data read from a file into memory are exactly identical. Therefor it suggests that CreateIconFromResource should work on normal regular memory as well. However there is one fundamental difference. Memory of the embeddable resources reside in special sections in the executable which are often padded to the nearest 4096-byte boundary. Memory allocated at runtime contains garbage values.
Now the solution that I found working exploits this by simply allocating a guard-band of zero-filled bytes. In my own test cases I have found that 8 is the minimum which also happens to be the size of a chunk in the riff container. Coincidence? What i suspect is that this is a bug and the algorithm happens to work for embeddable resources due to it's alignment restrictions within the dll/executable.
const int guardbandSize = 8;
FILE* fs = fopen("action.ani", "rb");
fseek(fs, 0,SEEK_END); int dwSize = ftell(fs); fseek(fs, 0,SEEK_SET);
char* memory = new char[dwSize + guardbandSize];
fread(memory, 1, dwSize, fs); memset(memory + dwSize, 0, guardbandSize);
fclose(fs);
cursor = (HCURSOR)CreateIconFromResource((PBYTE)memory,dwSize,FALSE,0x00030000);
delete memory;
Here is an overview of various ways to load an animated cursors.
#include <Windows.h>
#include <stdio.h>
#include "resource2.h"
void* hWnd;
bool visible = true;
bool running = true;
LRESULT CALLBACK WndProcInternal( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ;
HCURSOR cursor = 0;
void main()
{
//Setup configuration
const int Width = 640, Height = 480;
const int Method = 4;
//Setup window class
WNDCLASS wcd;
wcd.style = CS_PARENTDC | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcd.lpfnWndProc = (WNDPROC)WndProcInternal;
wcd.cbClsExtra = 0;
wcd.cbWndExtra = 0;
wcd.hInstance = GetModuleHandle(NULL);
wcd.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wcd.hCursor = LoadCursor(NULL, IDC_ARROW);
wcd.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
wcd.lpszMenuName = NULL;
wcd.lpszClassName = TEXT("AnimatedIcon");
//Register the window class
if(!RegisterClass(&wcd))
{
MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),MB_ICONEXCLAMATION | MB_OK);
FatalExit(-1);
}
//Create a window
if (!(hWnd=CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("AnimatedIcon"), TEXT("AnimatedIcon"),
WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_SYSMENU,
0, 0, Width, Height, NULL, NULL, NULL, NULL)))
{
MessageBoxA(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
FatalExit(-1);
}
if( Method == 1 )
{
//Method 1: Load cursor directly from a file
cursor = LoadCursorFromFileA("action.ani");
}
if( Method == 2 )
{
//Method 2: Load cursor from an resource section in the executable.
cursor = LoadCursor(0, MAKEINTRESOURCE(IDR_ANICURSORS1));
}
if( Method == 3 )
{
//Method 3: Manually locate the resource section in the executable & create the cursor from the memory.
HINSTANCE hInst=GetModuleHandle(0);
HRSRC hRes=FindResourceA(hInst,MAKEINTRESOURCEA(IDR_ANICURSORS1),"ANICURSORS");
DWORD dwSize=SizeofResource(hInst,hRes);
HGLOBAL hGlob=LoadResource(hInst,hRes);
LPBYTE pBytes=(LPBYTE)LockResource(hGlob);
cursor = (HCURSOR)CreateIconFromResource(pBytes,dwSize,FALSE,0x00030000);
}
if( Method == 4 )
{
//Method 4: Load the cursor from a file into memory & create the cursor from the memory.
const int guardbandSize = 8;
FILE* fs = fopen("action.ani", "rb");
fseek(fs, 0,SEEK_END); int dwSize = ftell(fs); fseek(fs, 0,SEEK_SET);
char* memory = new char[dwSize + guardbandSize];
fread(memory, 1, dwSize, fs); memset(memory + dwSize, 0, guardbandSize);
fclose(fs);
cursor = (HCURSOR)CreateIconFromResource((PBYTE)memory,dwSize,FALSE,0x00030000);
delete memory;
}
//Set the cursor for the window and display it.
SetClassLong((HWND)hWnd, GCL_HCURSOR, (LONG)cursor);
while (running)
{
MSG wmsg;
if (PeekMessage(&wmsg, (HWND)hWnd, 0, 0, PM_REMOVE))
{
TranslateMessage(&wmsg);
DispatchMessage(&wmsg);
}
}
}
LRESULT CALLBACK WndProcInternal( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if( uMsg == WM_DESTROY )
{
PostQuitMessage(1);
running = false;
}
return (long)DefWindowProc((HWND)hWnd,uMsg,(WPARAM)wParam,(LPARAM)lParam);
}
Import your animated cursor as a custom resource.
Give it a text name, eg "MyType".
Then load the cursor with:
HCURSOR hCursor = LoadAnimatedCursor(IDR_MYTYPE1, _T("MyType"));
/* ======================================================== */
HCURSOR LoadAnimatedCursor(UINT nID, LPCTSTR pszResouceType)
{
HCURSOR hCursor = NULL;
HINSTANCE hInstance = AfxGetInstanceHandle();
if (hInstance)
{ HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(nID), pszResouceType);
DWORD dwResourceSize = SizeofResource(hInstance, hResource);
if (dwResourceSize>0)
{ HGLOBAL hRsrcGlobal = LoadResource(hInstance, hResource);
if (hRsrcGlobal)
{ LPBYTE pResource = (LPBYTE)LockResource(hRsrcGlobal);
if (pResource)
{ hCursor = (HCURSOR)CreateIconFromResource(pResource, dwResourceSize, FALSE, 0x00030000);
UnlockResource(pResource);
}
FreeResource(hRsrcGlobal);
}
}
}
return hCursor;
}