Click here to Skip to main content
15,881,757 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
C++
int Num = 0;
LRESULT CALLBACK TestWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    RECT rc;
    GetClientRect(hWnd, &rc);
    RECT Winrc;
    GetWindowRect(hWnd, &Winrc);
    SYSTEMTIME time;
    GetLocalTime(&time);
    static const wchar_t* BoxTxt = L"";
    static int MeIs = Num;
    switch (message)
    {

    case WM_CREATE:
    {
        SetWindowLong(hWnd, GWL_EXSTYLE,
            GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
        SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 220, LWA_ALPHA);
        //GhWnd = hWnd;
        break;
    }
    case WM_LBUTTONUP:
    {
            wchar_t meChar[20] = L"";
            _itow(MeIs, meChar, 10);
            MessageBox(0, meChar, meChar, 0);
    }
    case WM_SIZE:
    {
        InvalidateRect(hWnd, &rc, 1);
        break;
    }
    case WM_NCLBUTTONDBLCLK:
    {
        break;
    }
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        switch (wmId)
        {

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;
    case WM_CLOSE:
    {
        Num -= 1;
        DestroyWindow(hWnd);
    }
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
int CreateTestWindow()
{
//Call testwndproc. To reduce the length of the problem description, omit these codes
Num+=1;
return 0;
}

In the above code, when I create multiple windows and click it, it should pop up "1", "2", "3"... But actually all pop up "1".

What I have tried:

static int MeIs = 0;
case WM_CREATE:
{
MeIs = Num;
}
Change to the above code and the serial number of the last window will pop up. For example, when the fourth window is created, all windows will pop up "4"
In practical application, each window has its own settings and is stored in the vector. Each window finds its own settings according to its own serial number
Any idea?thank you!
Posted
Updated 29-Nov-21 11:00am
v2

The problem is you have one instance of the variables of interest. If you want each window to have a unique number then they each have to a unique variable. There are several ways this could be implemented. Among them are a map that associates a number with a window handle.

Another possibility is to call the SetWindowLongPtr function and set the GWLP_USERDATA property to the identifier you want to give that window. Documentation can be found here : SetWindowLongPtrA function (winuser.h) - Win32 apps | Microsoft Docs[^].

When the window wants to display the value it can call GetWindowLongPtr as described here : GetWindowLongPtrA function (winuser.h) - Win32 apps | Microsoft Docs[^]. The value returned will be the identifier you assigned to it previously.
 
Share this answer
 
Comments
EnderMo233 28-Nov-21 5:01am    
Actually, I want to use it like this:
struct Data
{
int x;
int y;
int width;
int height;
const wchar_t* text;
}
std::vector<data>UserData(32);//Max:32
//then read them from file,But the window must know which window it is:UserData[i].
For example,the first window will set their coordinates to UserData[1].x and UserData[1].y,also need to save the file when closing.
Rick York 29-Nov-21 12:06pm    
OK, so use the data like that. A window can get its index into that vector as I showed you. I would make a class to contain the data and a method to get an index and/or pointer to a window's data. Here is a prototype you could use : Data * GetWindowData( HWND hwnd ); You can wrap all of this stuff up into one easy method call. There could be a corresponding SetWindowData method also.
merano99 28-Nov-21 17:03pm    
Numbering the windows with SetWindowLongPtr () seems to be a good solution if you write a consecutive number after creating the window. It is unclear which information should be stored in data.
As Rick York suggested numbering the windows with SetWindowLongPtr () seems to be a good solution if you write a consecutive number after creating the window.

Insted of using a MessageBox it is better to use the StatusBar:
C++
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Instanzenhandle in der globalen Variablen speichern

   HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
	  CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd) {
	  return FALSE;
   }

   statusbar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, _T("x"), hWnd, IDM_STATUS);

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

C++
void ShowWindowNumber(HWND hWnd)
{
	size_t x = GetWindowLongPtr(hWnd, GWLP_USERDATA);
	if ((x>=0) && (x < UserData.size())) {
		wchar_t meChar[20] = L"";
		wsprintf(meChar, _T("%ld"), x);
		SendMessageW(statusbar, SB_SETTEXT, 0, (LPARAM)meChar); 
	}
}


case WM_CREATE:
	{
		SetWindowLong(hWnd, GWL_EXSTYLE,
			GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
		SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 220, LWA_ALPHA);

		Data mydata;
		LONG_PTR chk, wn;

		// fill mydata for mainwindow here
		UserData.push_back(mydata);
		wn = (LONG_PTR)UserData.size() - 1;				  // get idx of last data
		chk = SetWindowLongPtrA(hWnd, GWLP_USERDATA, wn); // write idx of data

		but1 = CreateWindowW(L"BUTTON", L"OK",
			WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles 
			10, 10, 100, 100, hWnd, (HMENU)IDC_BUTTON1, 
			(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), NULL);

		// fill mydata for every subwindow here
		UserData.push_back(mydata);
		wn = (LONG_PTR)UserData.size() - 1;				  // get idx of last data
		chk = SetWindowLongPtrA(but1, GWLP_USERDATA, wn); // write idx of data
	}
 
Share this answer
 
v2
Comments
EnderMo233 29-Nov-21 0:11am    
Thank you, but there is another problem. If a window is closed, how do I inform the program to reorder all windows?
For example, if I close the second window (assuming there are five in total), the third window will be sorted as "2", and so on
merano99 29-Nov-21 16:28pm    
Windows that are closed do not generate any more messages. You could just leave the vector element unused.
Before you finally close the window you can of course delete the element from the vector, but you would then have to renumber all remaining windows.
To do this, you would have to write the window handle in the vector. But if this is needed anyway you can save the numbers completely. Simply search for the window handle and use the data under this index element.

Based on my first suggestion, here is another solution if you have to close windows in between.
C++
case WM_CREATE:
	{
		SetWindowLong(hWnd, GWL_EXSTYLE,
			GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
		SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 220, LWA_ALPHA);

		Data mydata;

		// fill mydata for mainwindow here
		mydata.hwnd = hWnd;
		UserData.push_back(mydata);

		HWND but1 = CreateWindowW(L"BUTTON", L"OK",
			WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles 
			10, 10, 100, 100, hWnd, (HMENU)IDC_BUTTON1,
			(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), NULL);

		// fill mydata for every subwindow here
		mydata.hwnd = but1;
		UserData.push_back(mydata);
	}

The vector element with the date can also be safely deleted shortly before the window is closed. With multithreading, however, it would make sense to secure searches and deletions with a mutex.

Here is the revised function to find the index:
C++
int FindWindowNumber(HWND hWnd)
{
	size_t x;     
	for (x = 0; x < UserData.size(); x++) {
		if (UserData[x].hwnd == hWnd)
			break;
	}
	
	if (x >= UserData.size())
		return -1;
	
	wchar_t meChar[20] = L"";
	wsprintf(meChar, _T("%ld"), x);
	SendMessageW(statusbar, SB_SETTEXT, 0, (LPARAM)meChar); 
	return (int)x;
}
 
Share this answer
 
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900