I have realised after so long of coding DirectX/OpenGL applications I don't have the faintest of ideas how to create windows with basic form objects like text boxes, labels, command buttons etc.
I can create a window using the CreateWindow function just fine, how can I add buttons, command prompts and other form objects to it?
Look at Create Window Help. Once you create your main window you can create child windows by providing the parent HWND to the function. For standard controls you use one of the class names defined at the button, like EDIT for an edit box and BUTTON for a button.
As an example: CreateWindow(L"BUTTON", L"Button", BS_TEXT | WS_CHILD | WS_VISIBLE, 40, 40, 100, 40, hMainWnd, (HMENU)ID_MYBUTTON, hInstance, NULL);
Or you could just create a dialog box instead and edit it with Visual Studio's resource editor (if you have full VS that is).
Related
I am incredibly confused by the whole "window" verses "listbox" thing in the WIN32 API. I am simply trying to create a window as a "listbox" and add elements to it. My end goal will be a listbox similar to the on here: http://msdn.microsoft.com/en-us/library/windows/desktop/hh298365%28v=vs.85%29.aspx
I start by create a window with a listbox like so:
hDlg = CreateWindowExA(
WS_EX_CLIENTEDGE,
"ListBox",
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
But from what I understand, hDlg now points to the entire window and not the listbox.
Ideally I want to be able to add items to the listbox similar to this:
int pos = (int)SendMessage(hwndList, LB_ADDSTRING, 0,
(LPARAM) "Test Item1");
However I cannot get the handle of the list in the same way as the tutorial because they use this line:
HWND hwndList = GetDlgItem(hDlg, IDC_LISTBOX_EXAMPLE);
but IDC_LISTBOX_EXAMPLE throws a compilation error because it isn't included anywhere. And for the life of me, I cannot google a correct result for the second parameter int nIDDlgItem.
Can someone please explain to me how I can find the value GetDlgItem() or otherwise find a handle to my listbox from CreateWindowExA()?
The problem is that you're using the predefined ListBox window class to create a top-level window.
hDlg = CreateWindowExA(WS_EX_CLIENTEDGE, "ListBox", ...
This is creating a listbox control. The second parameter to CreateWindowEx specifies the window class - this tells the system what type of window you want to create. Since you're passing "ListBox" for that value, it will be creating an instance of the ListBox class.
The trouble is that you're creating that window to be a top-level window. WS_OVERLAPPEDWINDOW is a window style used for top-level windows (i.e. the one titled "List Box Example" in the above screenshot). Child windows, such as the listbox control, need to have the WS_CHILD style set.
What you really need to do is use RegisterClass to register your own window class for the top-level window. You would use this class name when calling CreateWindowEx to create the main window, and then create the various controls as children of that window.
I have a button which is created in the WM_CREATE function of a Win32 Application with the following code:
hChangeWorldButton = CreateWindowEx(NULL,
"BUTTON",
"OK",
WS_CHILD | WS_VISIBLE | BS_FLAT | BS_BITMAP,
2,
2,
25,
25,
hWnd,
(HMENU)CHANGEWORLD_BUTTON,
GetModuleHandle(NULL),
NULL);
SendMessage(hChangeWorldButton, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)worldBmp);
I would like the button to show only the image. Not the background and border.
How can I do this? I have tried many different button styles from MSDN but nothing seems to fit my needs. I was thinking of using BS_OWNERDRAW but it seems a bit overkill. Or is it the only solution?
Finally, how can I change the cursor to be a hand when it's hovering over the button?
No button style is available that results in the visual representation you are after. You would have to go with BS_OWNERDRAW here.
As an alternative you could use a Static Control with the SS_NOTIFY style instead. A static control allows you to get the visual representation you want, and the SS_NOTIFY styles allows you to respond to mouse input. However, you will not be able to implement a keyboard interface.
While I have not tried this myself, it may also be possible to get the desired effect by using a Command Link (BS_COMMANDLINK), and setting the caption to an empty string.
To eliminate the button's background and border simply make the button smaller than the bitmap.
I am using CMFCTabCtrl in my dialog based application.
I need to add CPropertyPages to each tab or adding controls to each tab page.
I know from microsoft sample we can add control dynamically as follows
m_wnd1.Create (WS_CHILD | WS_VISIBLE, CRect (0, 0, 0, 0), &m_wndTabConfiguration, 1);
m_wnd1.SetFont (&afxGlobalData.fontRegular);
m_wnd1.SetWindowText (_T("Edit 1"));
m_wnd2.Create (WS_CHILD | WS_VISIBLE, CRect (0, 0, 0, 0), &m_wndTabConfiguration, 2);
m_wnd2.SetFont (&afxGlobalData.fontRegular);
m_wnd2.SetWindowText (_T("Edit 2"));
m_wndTabConfiguration.AddTab (&m_wnd1, _T("One"), 0, FALSE);
m_wndTabConfiguration.AddTab (&m_wnd2, _T("Two"), 1, FALSE);
Which is working fine.
But i want to design controls layout statically and show in tab pages.
Any help is heartily welcome...
If I understood your question correctly, you want to add controls on the different tabs in the CMFCTabCtrl? If so, I believe you can create the controls statically via either:
(1) Using the visual editor that comes with visual studio 2010, the visual editor will modify the .rc file of your project (can be found under the Resources filter) accordingly.
or
(2) You can edit the .rc file of your project directly by adding entries for new controls inside your dialog box.
Whichever method you choose, you will have to however place these controls in the correct positions ontop of the tab control! You then map the windows message that is related to a tab change by the user (check MSDN for proper info on the message id etc) and map it to a function in your dialog class (lets say OnTabChange) where you then determine which controls to hide and which to show (control.ShowWindow(SW_HIDE) or control.ShowWindow(SW_SHOW)) based on which tab is currently active/selected. The mapping is done similiar to how you would capture a button click event etc.
I am building a win32 application in visual studio 2012. I have 4 disabled buttons created with the following code:
HWND hWndButton=CreateWindowEx(NULL,
L"BUTTON",
L"APP1",
WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON|WS_DISABLED|BS_ICON,
40,
40,
180,
140,
hWnd,
(HMENU)IDC_BUTTON1,
GetModuleHandle(NULL),
NULL);
What I want to do is to enable the buttons as the application runs. I tried to use findwindow to find and enable the first button but it doesn't find it. My code is:
HWND hwB1 = FindWindow(L"BUTTON",L"APP1");
if (hwB1 !=0) MessageBox(NULL,L"FOUND",L"Button Found",MB_OK);
EnableWindow(hwB1,true);
Am I doing something wrong?
Thank you in advance.
FindWindow() finds top-level windows, not child windows.
If you really do want to look up a child window by name, you can use the FindWindowEx() function, but using the ID is usually more efficient.
The function that does this is GetDlgItem(). This looks up child windows by their ID, which you provide when you create them.
HWND hwB1 = GetDlgItem(hWnd, IDC_BUTTON1);
hWnd is the parent window, and IDC_BUTTON1 is the ID.
Another alternative is to simply store the window handle that's returned when you create the child window - hWndButton in your code example - and then you don't need to look it up at all.
Use FindWindowEx(),
HWND hwB1=FindWindowEx(hWnd/*Parent window*/,
hWndButton/*Child window*/,
"BUTTON"/*Class of the child window*/,
"APP1"/*Title of the child window*/);
This is a better method when the control ID is unknown.
I see in MSDN, it says:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx
If the created window is a child window, its default position is at the bottom of the Z-order. If the created window is a top-level window, its default position is at the top of the Z-order (but beneath all topmost windows unless the created window is itself topmost).
However, another documentation says:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632599(v=vs.85).aspx
When an application creates a window, the system puts it at the top of the z-order for windows of the same type
I tested it like this:
btn1 = ::CreateWindow(L"button", L"OK", WS_TABSTOP|BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD
, 10, 10, 50, 30, hWnd, (HMENU)51, hInst, NULL);
btn2 = ::CreateWindow(L"button", L"Cancel", WS_TABSTOP|WS_CHILD|BS_PUSHBUTTON|WS_VISIBLE
, 20, 20, 70, 30, hWnd, (HMENU)52, hInst, NULL);
I created two buttons in a window and they overlapped, I can see that the button created later is covering the first button created.
Is the first statement in MSDN contradictory to my testing?
The documentation is accurate. You are being tripped up by another problem, you allow the child windows to draw themselves across other child windows. So now the painting order matters.
You fix that by adding the WS_CLIPSIBLINGS style flag to your CreateWindowEx call. You'll now see that the OK button is on top. Fix:
btn1 = ::CreateWindow(L"button", L"OK",
WS_TABSTOP|BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS,
10, 10, 50, 30, hWnd, (HMENU)51, hInst, NULL);
// etc, use it as well on other child windows
You should not rely to much on the how the child windows are displayed and which one is drawn last. If I run your sample code I get an OK button which is overlapped by the Cancel button. If I move the mouse over the buttons then the OK button comes into foreground and draws over the Cancel button.
I once had similar trouble with overlapping child controls. Then I found out that Microsoft says Overlapping Controls Are Not Supported by Windows.
BTW, if you really want to see the Z-order, then use GetTopWindow and GetNextWindow. Or the simpler way: run Microsoft Spy++.