1

Using C++, I am making a Tic-Tac-Toe game using the Win32 API. To mark a square (X or O) I want the player to click the square which then changes to an X or O.

What I am doing right now is having a button click event which turns a static text box to X or O. However, when I place the button on top of the text box and make it not visible, I can't click it.

What I really need is an invisible button that still functions. So it's not set WS_VISIBLE, but you can still click it.

Is this possible or is there another way around this problem?

user7116
  • 63,008
  • 17
  • 141
  • 172
DonkeyKong
  • 1,005
  • 14
  • 18
  • 5
    Either let the static text box respond directly to WM_LBUTTONDOWN/WM_LBUTTONUP, or make the button visible and put an `X` or `O` for the button text. – Mark Ransom Jun 11 '13 at 19:09
  • Hey Mark, I think this is exactly what I want. I want to use WM_LBUTTONDOWN to change a certain box depending on where they clicked the mouse in the parent window. I am researching this on MSDN right now but any tips would be appreciated! – DonkeyKong Jun 11 '13 at 20:06

3 Answers3

2

I can see a couple of reasonable possibilities here.

The first and most obvious would be to skip using a button at all, and just have the underlying window process the WM_LBUTTONDOWN message, and set the "X" or "O" in the correct location. For this, you don't even need static controls -- you can just detect the mouse clicks directly on the parent window, and draw your "X" or "O" in the corresponding square.

Another possibility would be a button that's marked as "visible", but happens to be transparent. IMO, this is a fairly poor choice though. To do it, you'd need to either create a transparent button control on your own, or subclass a button control to disable its drawing.

At least IMO, the obvious route would be to skip using the static control at all. Instead, just use the buttons directly -- a button normally has a caption. Start with that caption as an empty string. When the button is clicked, change its caption to "X" or "O" as appropriate. It should probably also disable itself in response to the button click, so clicking it again won't have any further effect.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

There's no way to make an invisible button that still functions. Imagine all of the ways that could be abused if it were possible! Not to mention how confusing to have invisible, yet functional, UI.

What Mark Ransom posted is exactly right: you need to get your existing control to respond to mouse click events, just like a button does. Then you can do whatever you want in response to clicks. You don't need a button just to be clickable.

You say that you have a "static text box", but I'm not really sure what that is. There are text boxes (which are not static), and then there are static controls (which can display text). I'm going to assume that you have the latter.

In that case, you don't need to handle the WM_LBUTTONDOWN and WM_LBUTTONUP messages directly, which would require that you subclass the control. Although that's probably the best approach design-wise (separation of responsibilities and all that), it's also a lot more trouble.

Instead, you can handle the click events from the parent's window procedure by setting the SS_NOTIFY style for your static control (you can do this either in the Dialog Editor or in your call to CreateWindow, depending on how you create the control). This causes the control to notify its parent in four cases: when it is clicked (STN_CLICKED), when it is double-clicked (STN_DBLCLK), when it is enabled (STN_ENABLE), and when it is disabled (STN_DISABLE).

So at the parent, you need to process WM_COMMAND messages. The message you're looking for will have a HIWORD(wParam) of STN_CLICKED (indicating that a static control with the SS_NOTIFY style has been clicked), a LOWORD(wParam) corresponding to your static control's ID (set either in the Dialog Editor or specified as the hMenu parameter in your call to CreateWindow), and an lParam containing a handle to your static control.

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
0

If you use SW_HIDE, it doesn't just make the window invisible but makes it behave like that too. What you really wanted is probably just make the button transparent. I never did that, you may find this or this helpful.

You may just scrap the textbox just use the button, i mean a button-looking checkbox with ownerdraw or bitmaps. Or scrapping the button and handle the mouse events Like Mark suggests.

Community
  • 1
  • 1
Balog Pal
  • 16,195
  • 2
  • 23
  • 37
  • OK. Sorry my question is really bad now that I looked at it again. What I need is an invisible button that still functions. – DonkeyKong Jun 11 '13 at 19:36
  • Your first sentence is correct. But a "transparent" button is not going to respond to events either. Because it's transparent, the events will get passed on to the control underneath the button-that-is-not-there. – Cody Gray - on strike Jun 11 '13 at 20:38