Problem
I need to resize no border form,But when ChromiumWebBrowser's dock is fill, CEF will eat mouse related information, dragging the form becomes very insensitive.
I observed Google Chrome, when the mouse outside the form can be dragged to change the size of the form, how can I achieve the same effect as Google Chrome.
Update
I need drag to change form's size,and Draggable borderless window in CefSharp a lot of private code, I can't know how to implement it.for example, ChromeWidgetMessageInterceptor.SetupLoop,in the cefsharp source code, ChromeWidgetMessageInterceptor does not have SetupLoop.
Update2 Add the screenshot and the code
const int WM_MOUSEMOVE = 0x0200;
const int WM_MOUSELEAVE = 0x02A3;
const int WM_LBUTTONDOWN = 0x0201;
//
switch (message.Msg)
{
case WM_MOUSEMOVE:
var clientCursorPos = GetMousePoint(MousePosition);
var newE = new MouseEventArgs(MouseButtons.None, 0, clientCursorPos.X, clientCursorPos.Y, 0);
this.InvokeOnParent(delegate { this.OnMouseMove(newE); });
break;
case WM_LBUTTONDOWN:
if (Cursor != Cursors.Default)
{
//this.InvokeOnParent(delegate { this.ResizeForm(this.ResizeDir); });
this.InvokeOnParent(delegate
{
if (DesignMode) return;
var dir = -1;
switch (this.ResizeDir)
{
case ResizeDirection.BottomLeft:
dir = HTBOTTOMLEFT;
break;
case ResizeDirection.Left:
dir = HTLEFT;
break;
case ResizeDirection.Right:
dir = HTRIGHT;
break;
case ResizeDirection.BottomRight:
dir = HTBOTTOMRIGHT;
break;
case ResizeDirection.Bottom:
dir = HTBOTTOM;
break;
}
ReleaseCapture();
if (dir != -1)
{
SendMessage(Handle, WM_NCLBUTTONDOWN, dir, 0);
}
});
}
break;
case WM_MOUSELEAVE:
Console.WriteLine("WM_MOUSELEAVE");
break;
}
Mouse drag to change the size of the problem
Related
I am currently programming a simple game in SDL (PONG clone) where i must have a continuously key pressing.
The problem I have is that when i press a button it reacts, waits a short period and then continues to continuously key pressing.
I wonder how i get that little delay to go away.
Here is my code:
while (running)
{
while (SDL_PollEvent(&event))
{
//update the game
if (event.type == SDL_QUIT)
{
quit_game();
running = false;
}
if(event.type == SDL_KEYDOWN)
{
switch (event.key.keysym.sym)
{
case SDLK_DOWN:
move_paddle(UP);
break;
case SDLK_UP:
move_paddle(DOWN);
break;
default:
break;
}
}
}
draw_game();
move_ball();
SDL_Delay(15);
}
The first thing i did was i wanted to remove the small delay and get the movement of the paddle smoother. I introduced 2 new global bool variables to keep track on which key that was pressed down.
bool key_up = false;
bool key_down = false;
I initiate them with the value false because no key is currently pressed.
In my switch I set the value for these boolean variables to match what is currently pressed down.
if(event.type == SDL_KEYDOWN)
{
switch (event.key.keysym.sym)
{
case SDLK_DOWN:
key_up = true;
key_down = false;
break;
case SDLK_UP:
key_down = true;
key_up = false;
break;
default:
break;
}
}
Then in the first while-loop i make two if-cases for the two keys that can be pressed and call the movement function in these if-cases.
if (key_up)
move_paddle(UP);
else if (key_down)
move_paddle(DOWN);
When i did this the delay disappeared and the paddle movement was smooth but it also generated another probelm, the paddle could not stay still in one place (except the boundraries). I then realised that the code is only looking for a key that is pressed down and does not react to a key that is released.
I then figured out that if a key is released (in this case the UP key or the DOWN key) the two boolean values had to be set to false because no key was pressed down.
What I did was that I made another if-statement after the if(event.type == SDL_KEYDOWN) that would disable the movement of the paddle if no key was pressed down.
if (event.type == SDL_KEYUP)
{
key_down = false;
key_up = false;
}
When I implemented all of this in my code the game worked like a charm.
For those who are interested, here is my new final code:
int gameloop()
{
SDL_Event event;
bool running = true;
bool key_up = false;
bool key_down = false;
while (running)
{
while (SDL_PollEvent(&event))
{
//update the game
if (event.type == SDL_QUIT)
{
quit_game();
running = false;
}
if(event.type == SDL_KEYDOWN)
{
switch (event.key.keysym.sym)
{
case SDLK_DOWN:
key_up = true;
key_down = false;
break;
case SDLK_UP:
key_down = true;
key_up = false;
break;
default:
break;
}
}
if (event.type == SDL_KEYUP)
{
key_down = false;
key_up = false;
}
}
if (key_up)
move_paddle(UP);
else if (key_down)
move_paddle(DOWN);
move_ball();
ai_paddle_move();
draw_game();
printf("Player: %d | AI: %d\n", player, ai);
SDL_Delay(15);
}
return 1;
}
I have a UIScrollView into which I am creating and adding UILabels containing the results of a simple LINQ query.
I have set up a UISwipeGestureRecognizer within the loop that generates the labels (iOS: issues with UIGestureRecognisers vs Subviews says I need a new recogniser for each control - I'm assuming I can do with a UILabel the same as UIImageView for adding a recogniser) and then added the recogniser to the label.
When the view containing the UIScrollView is started, the scrollview works as expected, but the swipe isn't.
Caveat : only tried this on the simulator, my iPhone is acting up.
private void CreateViewHistory()
{
float xtext = 4f;
float y = 4f;
int c = 0;
var tv = tank.Events.OrderByDescending(t => t.Date).ToList();
tbiHistClearAll.Enabled = enableDelete;
//tgrRemove.AddTarget(this, new Selector("screenSwipe"));
//pgrRemove.DelaysTouchesBegan = true;
foreach (var e in tv)
{
var tgrRemove = new UISwipeGestureRecognizer()
{
NumberOfTouchesRequired = 1,
Direction = UISwipeGestureRecognizerDirection.Right,
};
tgrRemove.AddTarget(this, new Selector("screenSwipe"));
svHistoryEvents.PanGestureRecognizer.RequireGestureRecognizerToFail(tgrRemove);
string info = string.Format("{0} - {1}{2} ({3})\n{4} - {5}\n{6} - {7}\n{8} - {9}", e.EventType, e.Volume, AppDelegate.Self.db.getShortVolumeUnits(), e.Date.ToShortDateString(),
StringUtils.GetString("Sowcrop.Implement"), e.Implement != null ? e.Implement.ImplementType : StringUtils.GetString("Common.NonRecorded"),
StringUtils.GetString("Common.User"), StringUtils.GetString("Common.NonRecorded"),
StringUtils.GetString("Common.Notes"), !string.IsNullOrEmpty(e.Notes) ? e.Notes : StringUtils.GetString("Common.NonRecorded"));
var lbl = new UILabel()
{
UserInteractionEnabled = true
};
lbl = UICreation.MakeLabelWithTag(svHistoryEvents, new RectangleF(xtext, y, 320f, 90f), info, UITextAlignment.Left, UIColor.Black, false, 4, c);
lbl.AddGestureRecognizer(tgrRemove);
svHistoryEvents.AddSubview(lbl);
lblTemp.Add(lbl);
c++;
y += 94f;
}
UIUtils.ResizeScrollView(svHistoryEvents);
}
[Export("screenSwipe")]
public void SwipeRemove(UIGestureRecognizer s)
{
var swipe = s as UIGestureRecognizer;
var tv = tank.Events.OrderByDescending(t => t.Date).ToList();
var txt = swipe.View as UILabel;
switch (swipe.State)
{
case UIGestureRecognizerState.Began:
Console.WriteLine("Swipe began");
break;
case UIGestureRecognizerState.Changed:
Console.WriteLine("Swipe changed");
tv.RemoveAt(txt.Tag);
CreateViewHistory();
break;
case UIGestureRecognizerState.Ended:
Console.WriteLine("Swipe ended");
break;
case UIGestureRecognizerState.Cancelled:
Console.WriteLine("Swipe cancelled");
break;
}
}
MakeLabelWithTag generates a UILabel which can then be added to the scrollview.
Am I missing something here, or do I need to do something special as the label is held within a scrollview?
I've also tried what has been suggested at UISwipeGestureRecogniser in a UIScrollView, but still without success.
Found the problem and it's probably the dumbest thing I've encountered in a long time!
To get the swipe gesture to work within a scrollview, you have to first encompass whatever it is you want to add within a UIView and then add that to the scrollview.
To therefore get a swipe within a scrollview to work, you need to do the following
private void CreateViewHistory()
{
foreach (var i in svHistoryEvents.Subviews)
if (i is UIView)
i.RemoveFromSuperview();
float xtext = 4f;
float y = 4f;
int c = 0;
tbiHistClearAll.Enabled = enableDelete;
foreach (var e in tv)
{
var tgrRemove = new UISwipeGestureRecognizer()
{
NumberOfTouchesRequired = 1,
Direction = UISwipeGestureRecognizerDirection.Right,
};
tgrRemove.AddTarget(this, new Selector("screenSwipe"));
var view = new UIView(new RectangleF(xtext, y, 320f, 90f));
svHistoryEvents.PanGestureRecognizer.RequireGestureRecognizerToFail(tgrRemove);
string info = string.Format("{0} - {1}{2} ({3})\n{4} - {5}\n{6} - {7}\n{8} - {9}", e.EventType, e.Volume, AppDelegate.Self.db.getShortVolumeUnits(), e.Date.ToShortDateString(),
StringUtils.GetString("Sowcrop.Implement"), e.Implement != null ? e.Implement.ImplementType : StringUtils.GetString("Common.NonRecorded"),
StringUtils.GetString("Common.User"), StringUtils.GetString("Common.NonRecorded"),
StringUtils.GetString("Common.Notes"), !string.IsNullOrEmpty(e.Notes) ? e.Notes : StringUtils.GetString("Common.NonRecorded"));
var lbl = new UILabel()
{
UserInteractionEnabled = true
};
lbl = UICreation.MakeLabelWithTag(svHistoryEvents, new RectangleF(0, 0, 320f, 90f), info, UITextAlignment.Left, UIColor.Black, false, 4, c);
view.AddGestureRecognizer(tgrRemove);
view.AddSubview(lbl);
svHistoryEvents.AddSubview(view);
lblTemp.Add(lbl);
c++;
y += 94f;
}
UIUtils.ResizeScrollView(svHistoryEvents);
}
[Export("screenSwipe")]
public void SwipeRemove(UIGestureRecognizer s)
{
var swipe = s as UIGestureRecognizer;
var txt = swipe.View.Subviews[0] as UILabel;
switch (swipe.State)
{
case UIGestureRecognizerState.Began:
Console.WriteLine("Swipe began");
break;
case UIGestureRecognizerState.Changed:
Console.WriteLine("Swipe changed");
break;
case UIGestureRecognizerState.Ended:
Console.WriteLine("Swipe ended");
tv.RemoveAt(txt.Tag);
CreateViewHistory();
break;
case UIGestureRecognizerState.Cancelled:
Console.WriteLine("Swipe cancelled");
break;
}
}
It is not possible to add just a UILabel and have the swipe act on that, it has to be on a UIView with the label as a subview to it.
I'm having a problem with the Simple Directmedia Layer library. The following code draws a block on the screen when a mouse button is pressed:
SDL_Event event;
while(running){
while(SDL_PollEvent(&event)){
while(event.button.state == SDL_PRESSED){
SDL_PollEvent(&event);
//where to draw
boxRect.x = event.motion.x;
boxRect.y = event.motion.y;
//Draw to screen
SDL_FillRect(display,&boxRect,boxColor);
SDL_Flip(display);
}
// ...
}
// ...
}
It works fine until I move the mouse, why moving the mouse makes event.button.state untrue?
How can I work with both simultaneously (i.e. keep drawing while the button is pressed)?
The problem with your code is that you're calling SDL_PollEvent (documented here) twice. As said in the documentation:
If event is not NULL, the next event is removed from the queue and
stored in the SDL_Event structure pointed to by event.
Rearranging your code a bit, like getting rid of the second SDL_PollEvent, creating the proper flow for clicking, moving, releasing and extracting rendering from the input pumping should give you something like this:
SDL_Event Event;
while(running)
{
while(SDL_PollEvent(&Event))
{
switch(Event.type)
{
// Handle your drawing with a simple state machine:
case SDL_MOUSEBUTTONDOWN:
{
if(Event.button.button == SDL_BUTTON_LEFT)
{
if(stateMachine == Released)
{
// ... begin drawing
stateMachine = Dragging
}
}
break;
}
case SDL_MOUSEMOTION:
{
if(stateMachine == Dragging)
{
// ... update the extends of your rect
}
}
case SDL_MOUSEBUTTONUP:
{
if(Event.button.button == SDL_BUTTON_LEFT)
{
if(stateMachine != Released)
{
// ... finalize drawing... add the rect to a list? flush it?
stateMachine = Released;
}
}
}
case SDL_QUIT:
{
running = false;
break;
}
}
}
// Outside of your event pumping, update the graphics
SDL_FillRect(display,&boxRect,boxColor);
SDL_Flip(display);
}
event.button.state is a bit mask. It is declared as a char which can hold eight bits representing different states of the buttons.
typedef struct{
Uint8 type;
Uint8 state;
Uint16 x, y;
Sint16 xrel, yrel;
} SDL_MouseMotionEvent;
More information here,
http://www.libsdl.org/docs/html/sdlgetmousestate.html
http://www.libsdl.org/docs/html/sdlmousemotionevent.html
Thanks to emartel's answer, it's working as expected, here's the code:
SDL_Event event;
int drawing = 0;
while(running){
while(SDL_PollEvent(&event)){
switch(event.type){
//starts drawing when any mouse button is pressed
case SDL_MOUSEBUTTONDOWN:
drawing = 1;
boxRect.x = event.button.x;
boxRect.y = event.button.y;
break;
//keeps drawing while no button is released
case SDL_MOUSEMOTION:
if(drawing == 1){
boxRect.x = event.motion.x;
boxRect.y = event.motion.y;
}
break;
//stops drawing when any button is released
case SDL_MOUSEBUTTONUP:
drawing = 0;
break;
case SDL_QUIT:
running = 0;
break;
}
}
//draws to screen
if(drawing == 1){
SDL_FillRect(display,&boxRect,boxColor);
SDL_Flip(display);
}
}
i'm trying to make a custom windows 8 style button using windows C API. however when i try to draw the text on the button after i redraw the button nothing visible happens!
I even tried creating a static window as a child of the button and sending WS_ERASEBKGND message to it when i redraw the button but as soon as i redraw the button for the first time it disappears!
here is the window procedure for my custom button:
LRESULT CALLBACK ButtonWindowProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
//static HWND static_text_handle;
HDC hdc;
PAINTSTRUCT ps;
DWORD color;
HFONT font,holdFont;
static RECT rect;
wchar_t test[] = L"test";
TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT),TME_LEAVE,hwnd,HOVER_DEFAULT};
/*static*/ HBRUSH brush = CreateSolidBrush(RGB(20,30,40));
/*static*/ HBRUSH clicked_brush = CreateSolidBrush(RGB(40,50,60));
/*static*/ HBRUSH hover_brush = CreateSolidBrush(RGB(70,80,90));
//TrackMouseEvent(&tme);
switch(msg)
{
case WM_CREATE:
//static_text_handle = CreateWindowW(L"Static",L"test",WS_CHILD | WS_VISIBLE,0,0,20,20,hwnd,NULL,NULL,NULL);
//brush = ((struct custom_button_colors*)(lParam))->default_color;
//clicked_brush = ((struct custom_button_colors*)(lParam))->push_color;
//hover_brush = ((struct custom_button_colors*)(lParam))->hover_color;
break;
case WM_LBUTTONDOWN:
SendMessage(hwnd,WM_ERASEBKGND,(WPARAM)GetDC(hwnd),(LPARAM)LPARAM_L_DOWN);
break;
case WM_LBUTTONUP:
SendMessage(hwnd,WM_ERASEBKGND,(WPARAM)GetDC(hwnd),(LPARAM)LPARAM_L_UP);
break;
case WM_MOUSEMOVE:
//Beep(1000,1000);
TrackMouseEvent(&tme);
if (GetAsyncKeyState(VK_LBUTTON))
{
SendMessage(hwnd,WM_ERASEBKGND,(WPARAM)GetDC(hwnd),(LPARAM)LPARAM_L_DOWN);
}
else
{
SendMessage(hwnd,WM_ERASEBKGND,(WPARAM)GetDC(hwnd),(LPARAM)LPARAM_MOUSEHOVER);
}
break;
case WM_MOUSELEAVE:
SendMessage(hwnd,WM_ERASEBKGND,(WPARAM)GetDC(hwnd),(LPARAM)-1);
break;
case WM_ERASEBKGND:
GetClientRect(hwnd,&rect);
if (lParam == LPARAM_L_DOWN)
{
FillRect((HDC)wParam,&rect,clicked_brush);
}
else if (lParam == LPARAM_MOUSEHOVER)
{
FillRect((HDC)wParam,&rect,hover_brush);
break;
}
else
{
POINT mousepos;
GetCursorPos(&mousepos);
if (WindowFromPoint(mousepos) == hwnd)
{
FillRect((HDC)wParam,&rect,hover_brush);
}
else
{
FillRect((HDC)wParam,&rect,brush);
}
}
hdc = BeginPaint(hwnd,&ps);
color = GetSysColor(COLOR_BTNFACE);
SetBkColor(hdc,color);
font = CreateFontW(25, 0, 0, 0, FW_MEDIUM, 0, 0, 0, 0,0, 0, ANTIALIASED_QUALITY, 0, L"Tahoma");
holdFont = SelectObject(hdc, font);
TextOutW(hdc,200,200,test,lstrlenW(test));
SelectObject(hdc,holdFont);
DeleteObject(font);
EndPaint(hwnd,&ps);
break;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
return 0;
}
I'm an absolute beginner in windows programming so sorry if my question is trivial.
1) Do not use BeginPaint/EndPaint in WM_ERASEBKGND. Move that code in a WM_PAINT handler.
2) Use SetWindowLong and the GWL_USERDATA index for storing the button state (UP or DOWN) and use GetWindowLong for retrieving the current state.
3) Use SetCapture for capturing the mouse, starting with WM_LBUTTONDOWN. Update the state of the button (UP or DOWN) according to mouse position
4) Use RedrawWindow when you need painting to occur
I was writing an app using the Windows API, and I wanted to know how to make a listview with subitems that contain multi-colored text.
To clarify, here is a picture of how it is implemented in API Monitor:
Notice that in the "API" column, the text has multiple colors, like it is rich text or something. I was wondering how I would do this.
Someone told me to do something with custom-drawing, but he wasn't sure. I looked into it, and I handled NM_CUSTOMDRAW. Here is the result of my test:
And here is the code:
inline LRESULT HandleWM_NOTIFY(LPARAM lParam)
{
switch (((LPNMHDR)lParam)->code)
{
case NM_CUSTOMDRAW:
{
switch (((LPNMHDR)lParam)->idFrom)
{
case ID_LISTVIEW1:
{
LPNMLVCUSTOMDRAW lpNMLVCD = (LPNMLVCUSTOMDRAW)lParam;
if (lpNMLVCD->nmcd.dwDrawStage == CDDS_PREPAINT)
{
return CDRF_NOTIFYITEMDRAW;
}
else if (lpNMLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
{
COLORREF crText;
switch (lpNMLVCD->nmcd.dwItemSpec % 3)
{
case 0:
crText = RGB(255, 0, 0);
break;
case 1:
crText = RGB(0, 255, 0);
break;
case 2:
crText = RGB(0, 0, 255);
break;
}
lpNMLVCD->clrText = crText;
lpNMLVCD->
}
return CDRF_DODEFAULT;
}
default: break;
}
break;
}
default: break;
}
return 0;
}
Using the NM_CUSTOMDRAW method, I can't modify the font colors of individual characters; I can only modify the font color of everything in the subitem, which is not what I want.
How can I achieve what API monitor does? I have a feeling this is going to be very difficult, but any suggestions are welcome.
NM_CUSTOMDRAW is the solution. Sorry to say there's no easy solution here. You simply need to ownerdraw the text you want in different colours sequentially rather than collectively, use the GetTextExtentPoint32 API to assist in the text drawing. You return CDRF_SKIPDEFAULT to tell the listview not to render the text, you took care of it.
if (lpNMHdr->code == NM_CUSTOMDRAW)
{
LPNMLVCUSTOMDRAW lpCD = (LPNMLVCUSTOMDRAW)lpNMHdr;
if (lpCD->nmcd.dwDrawStage == CDDS_PREPAINT)
{
return CDRF_NOTIFYITEMDRAW;
}
if (lpCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
{
return CDRF_NOTIFYSUBITEMDRAW;
}
if (lpCD->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT|CDDS_SUBITEM))
{
if (lpCD->iSubItem == 0) //detect which subitem is being drawn
{
LPCTSTR lpcszBuf1 = _T("example");
LPCTSTR lpcszBuf2 = _T("text");
RECT iR = { 0 };
ListView_GetSubItemRect(lpCD->nmcd.hdr.hwndFrom, lpCD->nmcd.dwItemSpec, lpCD->iSubItem, LVIR_BOUNDS, &iR);
SetBkMode(lpCD->nmcd.hdc, TRANSPARENT);
SIZE sz = { 0 };
GetTextExtentPoint32(lpCD->nmcd.hdc, lpcszBuf1, 7, &sz);
SetTextColor(lpCD->nmcd.hdc, RGB(255, 0, 0));
DrawText(lpCD->nmcd.hdc, lpcszBuf1, -1, &iR, DT_LEFT);
iR.left += sz.cx;
SetTextColor(lpCD->nmcd.hdc, RGB(0, 255, 0));
DrawText(lpCD->nmcd.hdc, lpcszBuf2, -1, &iR, DT_LEFT);
return CDRF_SKIPDEFAULT;
}
}