COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :

Go Back   Cockos Incorporated Forums > Other Software Discussion > WDL users forum

Reply
 
Thread Tools Display Modes
Old 05-12-2014, 11:52 PM   #1
doozle
Human being with feelings
 
doozle's Avatar
 
Join Date: May 2014
Location: East Palo Alto
Posts: 12
Default IEditableTextControl in WDL-OL - Is this safe/legit?

I need to provide a sign in function within my plugin. I'm using WDL-OL, and it looks like the only thing available for me to get text input is to have an IControl use IGraphics::CreateTextEntry(). This works well, but doesn't provide any option for hidden/password style text.

I see that the Tale IPlug library(among others) supplies an IEditableTextControl class that supports these features. However that control relies on a specific IGraphics::PromptUserInput(IEditableTextControl*) overload for this functionality.

The implementations for Tale PromptUserInput() and WDL-OL CreateTextEntry() are nearly identical. So I added the following in the IGraphicsWin class:
Code:
void IGraphicsWin::CreateTextEntryStyle(IControl* pControl, IText* pText, IRECT* pTextRect, const char* pString, IParam* pParam, bool pIsSecure, bool pIsEditable)
{
	if (!pControl || mParamEditWnd) return;

	DWORD editStyle;

	switch ( pText->mAlign )
	{
		case IText::kAlignNear:   editStyle = ES_LEFT;   break;
		case IText::kAlignFar:    editStyle = ES_RIGHT;  break;
		case IText::kAlignCenter:
		default:                  editStyle = ES_CENTER; break;
	}
	// Biggest difference from orignal function
	if (!pIsEditable) editStyle |= ES_READONLY;
	if (pIsSecure)
		editStyle |= ES_PASSWORD;
	else
		editStyle |= ES_MULTILINE;

  mParamEditWnd = CreateWindow("EDIT", pString, WS_CHILD | WS_VISIBLE | editStyle ,
                               pTextRect->L, pTextRect->T, pTextRect->W()+1, pTextRect->H()-2,  // Original WDL-OL function use ->H()+1. Why? Just added whitespace to the bottom
                               mPlugWnd, (HMENU) PARAM_EDIT_ID, mHInstance, 0);

  HFONT font = CreateFont(pText->mSize, 0, 0, 0, pText->mStyle == IText::kStyleBold ? FW_BOLD : 0, pText->mStyle == IText::kStyleItalic ? TRUE : 0, 0, 0, 0, 0, 0, 0, 0, pText->mFont);

  SendMessage(mParamEditWnd, WM_SETFONT, (WPARAM) font, 0);	
  SendMessage(mParamEditWnd, EM_SETSEL, 0, -1);
  Edit_LimitText(mParamEditWnd, pControl->GetTextEntryLength());		
  SetFocus(mParamEditWnd);

  mDefEditProc = (WNDPROC) SetWindowLongPtr(mParamEditWnd, GWLP_WNDPROC, (LONG_PTR) ParamEditProc);	
  SetWindowLong(mParamEditWnd, GWLP_USERDATA, (LPARAM) this);
  //SetWindowLongPtr(mParamEditWnd, GWLP_USERDATA, 0xdeadf00b); //this was from the Tale repo. For key input???

  //DeleteObject(font);

  mEdControl = pControl;
  mEdParam = pParam; // could be 0
}
I added my own IEditableTextControl class that calls this function instead of PromptUserInfo() - and it works! I realize this is windows specific, and I will need to address the Mac side of it as well.

When using this new function I noticed that using password style text would give my input a box a white background, regardless of my controls mText.mTextEntryBGColor

To fix that I altered IGraphicsWin::WndProc():
Code:
    case WM_CTLCOLOREDIT:
    {

      if(!pGraphics->mEdControl)
        return 0;

      IText* pText = pGraphics->mEdControl->GetText();
      HDC dc = (HDC) wParam;
      SetBkColor(dc, RGB(pText->mTextEntryBGColor.R, pText->mTextEntryBGColor.G, pText->mTextEntryBGColor.B));
      SetTextColor(dc, RGB(pText->mTextEntryFGColor.R, pText->mTextEntryFGColor.G, pText->mTextEntryFGColor.B));
	  SetBkMode(dc, OPAQUE);
      //return (BOOL)GetStockObject(DC_BRUSH);
      
	  // Added this:
	  HBRUSH hBrush = CreateSolidBrush(RGB(pText->mTextEntryBGColor.R, pText->mTextEntryBGColor.G, pText->mTextEntryBGColor.B));
	  SelectObject((HDC)wParam, (HGDIOBJ)hBrush);
	  return (BOOL)hBrush;
    }
The difference is using CreateSolidBrush() instead of GetStockBrush(). This works well for ES_PASSWORD, but when using ES_READONLY, the background gets set to gray regardless. I don't know why.

I'm new to IPlug and I don't fully understand how everything in IGraphics might be interacting with these changes I made. So I'm wondering if this is the right/safe way to get these features.

Bonus Questions
-within WDL-OL CreateTextEntry(), the CreateWindow() call passes pTextRect->W+1 and pTextRect->H()+1. Whats the reason behind adding +1. H()+1 was adding white space to bottom of colored background area.

-Tale's PromptUserInput() uses the line
Code:
SetWindowLongPtr(mParamEditWnd, GWLP_USERDATA, 0xdeadf00b);
and WDL-OL uses the line
Code:
SetWindowLong(mParamEditWnd, GWLP_USERDATA, (LPARAM) this);
What's going on there?


Finally: Thank you.
doozle is offline   Reply With Quote
Old 05-13-2014, 03:37 PM   #2
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,646
Default

Quote:
Originally Posted by doozle View Post
-Tale's PromptUserInput() uses the line
Code:
SetWindowLongPtr(mParamEditWnd, GWLP_USERDATA, 0xdeadf00b);
and WDL-OL uses the line
Code:
SetWindowLong(mParamEditWnd, GWLP_USERDATA, (LPARAM) this);
What's going on there?
It enables you to input keys that would normally be intercepted by REAPER, like e.g. the spacebar. Some more info:
http://forum.cockos.com/showthread.p...ght=0xdeadf00b

However, if you want to use it you will also have to modify ParamEditProc(), because it expects GWLP_USERDATA to be a HWND, not 0xdeadf00b (see commit 4e453e2495 in my WDL repository).
Tale is offline   Reply With Quote
Old 05-13-2014, 11:24 PM   #3
doozle
Human being with feelings
 
doozle's Avatar
 
Join Date: May 2014
Location: East Palo Alto
Posts: 12
Default

Great info. 0xdeadf00b seems like a useful addition. Did you implement a parallel OSX friendly solution for this key stealing problem?

News: I mentioned earlier that I couldn't set the bg color for read-only text boxes(they default to gray). It turns out that read-only edit controls don't send the WM_CTLCOLOREDIT message. The solution is to simply handle WM_CTLCOLORSTATIC. This is as easy as inserting:
Code:
case WM_CTLCOLORSTATIC:
right above the WM_CTLCOLORSEDIT case in the switch statement to let it fall through. Huzzah! Colored box!

I'm eager to fiddle with the OSX implementation, but I don't have a mac to test with. Hmmm...

Does anybody else find this useful? Again, feedback from anyone who has a better understanding of IGraphics would be well received.

Last edited by doozle; 05-14-2014 at 01:11 AM. Reason: typo
doozle is offline   Reply With Quote
Old 05-15-2014, 02:58 PM   #4
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,646
Default

Quote:
Originally Posted by doozle View Post
Great info. 0xdeadf00b seems like a useful addition. Did you implement a parallel OSX friendly solution for this key stealing problem?
No, but I don't think it is necessary on OSX.
Tale is offline   Reply With Quote
Old 05-15-2014, 03:06 PM   #5
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,646
Default

BTW, I think you should delete a brush created with CreateSolidBrush(). Creating a new brush each time a WM_CTLCOLORSEDIT is sent and never deleting any of them will probably cause memory to leak.
Tale is offline   Reply With Quote
Old 05-17-2014, 03:42 PM   #6
doozle
Human being with feelings
 
doozle's Avatar
 
Join Date: May 2014
Location: East Palo Alto
Posts: 12
Default

Ah that's correct. I understand I must use DeleteObject(). But I don't know where this ought to be done. Should this be done when handling WM_DESTORY?

Last edited by doozle; 05-17-2014 at 03:48 PM.
doozle is offline   Reply With Quote
Old 05-18-2014, 01:09 AM   #7
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,646
Default

Quote:
Originally Posted by doozle View Post
Ah that's correct. I understand I must use DeleteObject(). But I don't know where this ought to be done. Should this be done when handling WM_DESTORY?
Yeah, or maybe in the IGraphicsWin destructor... And I guess you would have to create the brush only once, and then store it in a IGraphicsWin member variable.
Tale is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 08:51 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.