|
|
MakeMusic Forum > Public Forums > Plug-In Development - FORUM HAS MOVED! > Plug-in for Finale: a very easy method of playing music on the MIDI keyboard. | Forum Quick Jump
|
| author Registered Member
Date Joined Mar 2015 Total Posts : 30 | Posted Yesterday 2:30 PM (GMT -6) | | This plug-in returned to its original name PlayMusic. Accordingly, the site has moved to www.playmusic-finale.com. Now available PlayMusic 18.5.0.1 for Windows. Any version of PlayMaster can be updated to PlayMusic for free. If you have already authorized PlayMaster, then re-authorization is not required. | Back to Top | |
| author Registered Member
Date Joined Mar 2015 Total Posts : 30 | Posted Today 7:05 AM (GMT -6) | | How to draw a cursor similar to the Finale’s playback cursor?
First, declare the global variables and function:
HWND hDrawWnd; //handle of the window where you want to draw the cursor HDC hDrawDC, hDrawCompDC, hCursCompDC; HBITMAP hBitmap, hCursBitmap; SIZE *pSizeDrawWnd; COLORREF rgbCursor; //color of the cursor
void __stdcall DrawCursor(int nHorz, int nBottom, int nTop, bool bDrawFlag);
Then, insert the following text into FinaleExtensionInvoke():
int nHorz, nVertBottom, nVertTop; pSizeDrawWnd =new SIZE; RECT *pRectDrawWnd = new RECT; GetClientRect(hDrawWnd, pRectDrawWnd); pSizeDrawWnd->cx = pRectDrawWnd->right; pSizeDrawWnd->cy = pRectDrawWnd->bottom; delete pRectDrawWnd;
hDC=GetDC(hDrawWnd); hCompDC=CreateCompatibleDC(hDC); hBitmap=CreateCompatibleBitmap(hDC, pSizeDrawWnd->cx, pSizeDrawWnd->cy); SelectObject(hCompDC, (HGDIOBJ)hBitmap);
BitBlt(hCompDC, 0, 0, pSizeDrawWnd->cx, pSizeDrawWnd->cy, hDC, 0, 0, SRCCOPY);
hCursCompDC=CreateCompatibleDC(hDC); hCursBitmap=CreateCompatibleBitmap(hDC, 4, pSizeDrawWnd->cy); SelectObject(hCursCompDC, (HGDIOBJ)hCursBitmap); for(int nX=0; nX<2; nX++) for(int nY=0; nY<pSizeDrawWnd->cy; nY++) SetPixel(hCursCompDC, nX, nY, rgbCursor); //.......................................................................................... DrawCursor(nHorz, nVertBottom, nVertTop, true); //draw cursor //.......................................................................................... DrawCursor(nHorz, nVertBottom, nVertTop, false); //restore previous image //.......................................................................................... DeleteObject((HGDIOBJ)hBitmap); DeleteDC(hCompDC);
DeleteObject((HGDIOBJ)hCursBitmap); DeleteDC(hCursCompDC); DeleteDC(hDC); delete pSizeDrawWnd;
And finally, here is the declared above function:
void __stdcall DrawCursor(int nHorz, int nBottom, int nTop, bool bDrawFlag) { UINT uArrowBitMask[12]={0x20, 0x20, 0x70, 0x70, 0xF8, 0xF8, 0x1FC, 0x1FC, 0x3FE, 0x3FE, 0x707, 0x401};
if(nHorz<0) nHorz=0; else if(nHorz>=pSizeDrawWnd->cx) nHorz=pSizeDrawWnd->cx-1; if(nTop<0) { nTop=0; if(nBottom<0) nBottom=0; } else if(nBottom>=pSizeDrawWnd->cy) { nBottom=pSizeDrawWnd->cy-1; if(nTop>=pSizeDrawWnd->cy) nTop=pSizeDrawWnd->cy-1; }
int nPixelCount=0; for(int nY=0; nY<12; nY++) if((nTop-nY>=0)&&(nTop-nY<pSizeDrawWnd->cy)) for(int nX=0, uBitMask=1; nX<11; nX++, uBitMask<<=1) if((nHorz+5-nX>=0)&&(nHorz+5-nX<pSizeDrawWnd->cx)) { if(uBitMask&uArrowBitMask[nY]) if(bDrawFlag) { BitBlt(hCursCompDC, 2, nPixelCount, 1, 1, hCompDC, nHorz+5-nX, nTop-nY, SRCCOPY); BitBlt(hDC, nHorz+5-nX, nTop-nY, 1, 1, hCursCompDC, 0, 0, SRCCOPY); } else BitBlt(hDC, nHorz+5-nX, nTop-nY, 1, 1, hCursCompDC, 2, nPixelCount, SRCCOPY); nPixelCount++; }
if(bDrawFlag) { BitBlt(hCursCompDC, 3, nTop+1, 1, nBottom-nTop, hCompDC, nHorz, nTop+1, SRCCOPY); BitBlt(hDC, nHorz, nTop+1, 1, nBottom-nTop, hCursCompDC, 1, nTop+1, SRCCOPY); } else BitBlt(hDC, nHorz, nTop+1, 1, nBottom-nTop, hCursCompDC, 3, nTop+1, SRCCOPY); } Post Edited (author) : 12/21/2015 2:22:32 AM (GMT-6) | Back to Top | |
| author Registered Member
Date Joined Mar 2015 Total Posts : 30 | Posted 12/21/2015 1:11 PM (GMT -6) | | How to find the current color of the Finale's playback cursor?
File FINALE.INI keeps the settings (including the color of the playback cursor) from the previous run of Finale. To find the actual value of the cursor's color, you should open Select Display Colors item in View menu, get a pixel from Playback Cursor window, and then close Preferences - Display Colors window. But, of course, necessary that all opened windows were practically invisible.
Declare the global variables and functions:
HWND hFinaleWnd; HHOOK hDialogHook; HDC hScreenDC, hScreenCompDC; //27.03.12 HBITMAP hScreenBitmap; int nDialogChildWnd; int nFinDispWnd;
//WNDPROC wpFinaleWndProc; struct TWndProc { WNDPROC wpWndProc; //WNDPROC for Visual C++; FARPROC for C++ Builder; HWND hWnd; }; TWndProc* lpDialog;
int __stdcall DialogHookProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK NewDialogWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
Insert this text into FinaleExtensionInvoke():
Sleep(1000); //----------------------------------------------------------------------------------------------------------------------------------- hFinaleWnd=hWnd; hScreenDC=GetWindowDC(NULL); hScreenCompDC=CreateCompatibleDC(hScreenDC); int nScreenWidth=GetSystemMetrics(SM_CXSCREEN); int nScreenHeight=GetSystemMetrics(SM_CYSCREEN); hScreenBitmap=CreateCompatibleBitmap(hScreenDC, nScreenWidth, nScreenHeight); SelectObject(hScreenCompDC, (HGDIOBJ)hScreenBitmap);
HMENU hMenu=GetMenu(hFinaleWnd); int nPosViewItem=4; //for Finale 2008-2014.5 // nPosViewItem=3; //for Finale 2004-2007 HMENU hMenuView=GetSubMenu(hMenu, nPosViewItem);
int nPosSelectDisplayColorsItem=16; //for Finale 2012b-2014.5 // nPosSelectDisplayColorsItem=6; //for Finale 2004-2005 // nPosSelectDisplayColorsItem=7; //for Finale 2006-2007 // nPosSelectDisplayColorsItem=14; //for Finale 2008 // nPosSelectDisplayColorsItem=15; //for Finale 2009-2012a
ANIMATIONINFO animation; animation.cbSize=sizeof(ANIMATIONINFO); SystemParametersInfo(SPI_GETANIMATION, sizeof(ANIMATIONINFO), &animation, SPIF_UPDATEINIFILE); int nMinAnimate=animation.iMinAnimate;
animation.iMinAnimate=0; SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &animation, SPIF_SENDWININICHANGE); lpDialog=(TWndProc*)calloc(256, sizeof(TWndProc)); hDialogHook=SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)DialogHookProc, NULL, GetCurrentThreadId()); nFinDispWnd=0; BitBlt(hScreenCompDC, 0, 0, nScreenWidth, nScreenHeight, hScreenDC, 0, 0, SRCCOPY);
SendMessage(hFinaleWnd, WM_COMMAND, GetMenuItemID(hMenuView, nPosSelectDisplayColorsItem), NULL); //open Select Display Colors item in View menu BitBlt(hScreenDC, 0, 0, nScreenWidth, nScreenHeight, hScreenCompDC, 0, 0, SRCCOPY); UnhookWindowsHookEx(hDialogHook); free((TWndProc*)lpDialog); animation.iMinAnimate=nMinAnimate; SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &animation, SPIF_SENDWININICHANGE);
DeleteObject((HGDIOBJ)hScreenBitmap); DeleteDC(hScreenCompDC); DeleteDC(hScreenDC); //------------------------------------------------------------------------------------------------------------------------------------------------------- char szText[80]; wsprintf(szText, " rgbCursor= %x\n ", rgbCursor); MessageBox( hFinaleWnd, szText, "Playback Cursor", MB_OK | MB_ICONASTERISK );
Here are DialogHookProc() and NewDialogWndProc():
int __stdcall DialogHookProc(int nCode, WPARAM wParam, LPARAM lParam) { if(nCode>=0) { if(((CWPSTRUCT*)lParam)->message==WM_NCCREATE) { if(((LPCREATESTRUCT)((CWPSTRUCT*)lParam)->lParam)->hwndParent==hFinaleWnd) nDialogChildWnd=0; (lpDialog+nDialogChildWnd)->hWnd=((CWPSTRUCT*)lParam)->hwnd; (lpDialog+nDialogChildWnd)->wpWndProc= (WNDPROC)SetWindowLongPtr((lpDialog+nDialogChildWnd)->hWnd, GWLP_WNDPROC, (LONG_PTR)NewDialogWndProc); nDialogChildWnd++; } return 0; } else return CallNextHookEx(hDialogHook, nCode, wParam, lParam); }
LRESULT CALLBACK NewDialogWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static bool bCloseDialog; static RECT rectWnd; static int nNCPaintCount; RECT rectClient; POINT pointLeftUp; HDC hCurrDC; bool bFinDispWnd; bool bCompFinaleDC; int nChildWnd; char buf[80];
int nPlaybackCursorFinDispWnd=20; //for Finale 2012.b-2014.5 // nPlaybackCursorFinDispWnd=19; //for Finale 2004 // nPlaybackCursorFinDispWnd=20; //for Finale 2005-2008 // nPlaybackCursorFinDispWnd=19; //for Finale 2009-2012a
int nFinDispWndNums=24; //for Finale 2012.b-2014.5 // nFinDispWndNums=21; //for Finale 2004 // nFinDispWndNums=22; //for Finale 2005-2006 // nFinDispWndNums=24; //for Finale 2007-2008 // nFinDispWndNums=23; //for Finale 2009-2012a
bCompFinaleDC=false; GetClassName(hWnd, buf, sizeof(buf));
for(nChildWnd=0; nChildWnd<nDialogChildWnd; nChildWnd++) if(hWnd==(lpDialog+nChildWnd)->hWnd) break;
switch(uMsg) { case WM_NCCREATE: { if(hWnd==lpDialog->hWnd) { nNCPaintCount=0; SetWindowRgn(hWnd, CreateRectRgn(0, 0, 0, 0), true); } return CallWindowProc((WNDPROC)(lpDialog+nChildWnd)->wpWndProc, hWnd, uMsg, wParam, lParam); }
case WM_CREATE: { if(hWnd==lpDialog->hWnd) bCloseDialog=false; return CallWindowProc((WNDPROC)(lpDialog+nChildWnd)->wpWndProc, hWnd, uMsg, wParam, lParam); }
case WM_NCPAINT: { if(hWnd==lpDialog->hWnd) { if(nNCPaintCount++==0) SetWindowRgn(lpDialog->hWnd, CreateRectRgn(0, 0, 0, 0), true); GetWindowRect(hWnd, &rectWnd);
CallWindowProc((WNDPROC)lpDialog->wpWndProc, hWnd, uMsg, wParam, lParam); } //end: if(hWnd==lpDialog->hWnd) } //end: case WM_NCPAINT break;
case WM_PAINT: { GetClientRect(hWnd, &rectClient); pointLeftUp.x=rectClient.left; pointLeftUp.y=rectClient.top; ClientToScreen(hWnd, &pointLeftUp);
if(strcmp(buf, "FinDisp")==0) { SetWindowRgn(lpDialog->hWnd, CreateRectRgn(pointLeftUp.x-rectWnd.left, pointLeftUp.y-rectWnd.top, pointLeftUp.x-rectWnd.left+1, pointLeftUp.y-rectWnd.top+1), false); hCurrDC=GetDC(hWnd); bFinDispWnd=true; } else bFinDispWnd=false; CallWindowProc((WNDPROC)(lpDialog+nChildWnd)->wpWndProc, hWnd, uMsg, wParam, lParam);
if(bFinDispWnd) { nFinDispWnd++; if(nFinDispWnd==nPlaybackCursorFinDispWnd) rgbCursor=GetPixel(hCurrDC, 0, 0); //color of the Finale's playback cursor
if(nFinDispWnd==nFinDispWndNums) bCloseDialog=true;
BitBlt(hCurrDC, 0, 0, 1, 1, hScreenCompDC, pointLeftUp.x, pointLeftUp.y, SRCCOPY); ReleaseDC(hWnd, hCurrDC); }
if(bCloseDialog) { bCloseDialog=false; BitBlt(hScreenDC, rectWnd.left, rectWnd.top, rectWnd.right-rectWnd.left, rectWnd.bottom-rectWnd.top, hScreenCompDC, rectWnd.left, rectWnd.top, SRCCOPY);
PostMessage(lpDialog->hWnd, WM_KEYDOWN, VK_RETURN, 0); //close Preferences - Display Colors window PostMessage(lpDialog->hWnd, WM_KEYUP, VK_RETURN, 0); }
} //end: case WM_PAINT break;
default: return CallWindowProc((WNDPROC)(lpDialog+nChildWnd)->wpWndProc, hWnd, uMsg, wParam, lParam); } //end: switch(Msg) return 0l; }
Post Edited (author) : 4/6/2016 9:40:50 AM (GMT-5) | Back to Top | |
| author Registered Member
Date Joined Mar 2015 Total Posts : 30 | Posted 12/31/2015 8:36 AM (GMT -6) | | And finally, how to find a handle of the window where you want to draw the cursor?
If you want to draw in one of the Finale’s child windows, then it can be selected, for instance, using Win API function EnumChildWindows(). First declare the global variable and function.
HWND hFinaleWnd; bool __stdcall EnumChildTest(HWND hWnd, LPARAM lParam);
Then insert this code into FinaleExtensionInvoke():
hFinaleWnd=hWnd; //........................................................................................................................................................... EnumChildWindows(hFinaleWnd, (WNDENUMPROC)EnumChildTest, 0);
For all open child window the function EnumChildTest() shows the window class name, screen coordinates of the upper-left and lower-right corners (if the window is not hidden), and the window text (if such text exists).
bool __stdcall EnumChildTest(HWND hWnd, LPARAM lParam) { char szClassName[256]; int nClassNameLength=GetClassName(hWnd, szClassName, sizeof(szClassName)); if(nClassNameLength==0) return true;
LPRECT lpWndRect = new RECT; char szWndText[256]; bool bWndRectResult=false; if(IsWindowVisible(hWnd)) bWndRectResult=GetWindowRect(hWnd, lpWndRect); //The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
int nWndTextLength=SendMessage(hWnd, WM_GETTEXT, sizeof(szWndText), (LPARAM)(LPCTSTR)szWndText); char szText[640]; if(bWndRectResult) if(nWndTextLength>0) wsprintf(szText, "{%s} (%d, %d)-(%d, %d) \"%s\" \n", szClassName, lpWndRect->left, lpWndRect->top, lpWndRect->right, lpWndRect->bottom, szWndText); else wsprintf(szText, "{%s} (%d, %d)-(%d, %d) \n", szClassName, lpWndRect->left, lpWndRect->top, lpWndRect->right, lpWndRect->bottom); else if(nWndTextLength>0) wsprintf(szText, "{%s} (hidden) \"%s\" \n", szClassName, szWndText); else wsprintf(szText, "{%s} (hidden) \n", szClassName);
int nRetValue=MessageBox(hFinaleWnd, szText, "Child Window", MB_RETRYCANCEL|MB_ICONQUESTION|MB_DEFBUTTON1);
delete lpWndRect; if(nRetValue==IDCANCEL) return false; else return true; }
EnumChildTest() helps to know the correct class name of the desired window and count the number of previous windows from the same class. This is enough to uniquely identify the window.
Now it is easy to find the handle to the desired window. Re-declare the global variables, function and type:
struct TParamEnumChild { char* lpszWndClassName; int nSameClassWndNums; int nSameClassWndCount; HWND hResultWnd; }; HWND hFinaleWnd; HWND hDrawWnd; //handle of the window where you want to draw
bool __stdcall EnumChild(HWND hWnd, LPARAM lParam);
Instead of calling EnumChildWindows(hFinaleWnd, (WNDENUMPROC)EnumChildTest, 0), insert the following code into FinaleExtensionInvoke():
//hFinaleWnd=hWnd //............................................................................................ TParamEnumChild *lpEnumChildParams=new TParamEnumChild;
lpEnumChildParams->lpszWndClassName="window_class_name"; //replace it for the real window class name lpEnumChildParams->nSameClassWndNums=0; //if necessary, replace 0 for another number of previous windows //from the same class lpEnumChildParams->nSameClassWndCount=0; lpEnumChildParams->hResultWnd=0; EnumChildWindows(hFinaleWnd, (WNDENUMPROC)EnumChild, (LPARAM)lpEnumChildParams);
hDrawWnd=lpResultChildWndTemp->hResultWnd; //this is the handle value of the desired window
delete lpEnumChildParams;
if(hDrawWnd==0) { //............................................................................................................. MessageBox( hFinaleWnd, "Specified window was not found.", "Real Name of Your Plug-in", MB_OK | MB_ICONSTOP ); return NO; }
The code of EnumChild():
bool __stdcall EnumChild(HWND hWnd, LPARAM lParam) { char szClassName[256]; GetClassName(hWnd, szClassName, sizeof(szClassName));
if(strcmp(szClassName, ((TParamEnumChild*)lParam)->lpszWndClassName)==0) { if(((TParamEnumChild*)lParam)->nSameClassWndCount==((TParamEnumChild*)lParam)->nSameClassWndNums) { ((TParamEnumChild*)lParam)->hResultWnd=hWnd; return false; } ((TParamEnumChild*)lParam)->nSameClassWndCount; } return true; }
Post Edited (author) : 1/3/2016 3:37:44 AM (GMT-6) | Back to Top | |
| author Registered Member
Date Joined Mar 2015 Total Posts : 30 | Posted 1/9/2016 12:43 PM (GMT -6) | | And the most important question: how to define the coordinates of the cursor, to draw it between the top and bottom of the appropriate staff system vertically and exactly to one pixel to the left of the desired note or notes horizontally for any score position on the screen, whether for Scroll, or Page, or Studio View of the score?
Unfortunately, the forum format does not allow to answer this question here, because all it is most of the source code. As mentioned above, the size of the PlayMusic source code is about 1.2MB. Since the accessible Finale data structures (contained in PDK) are not sufficient for these purposes, it requires using various means of Win API. In some cases it is necessary to recognize the image on the screen. | Back to Top | | Forum Information | Currently it is Tuesday, December 19, 2023 6:03 PM (GMT -6) There are a total of 403,820 posts in 58,165 threads. In the last 3 days there were 0 new threads and 0 reply posts. View Active Threads
|
Forum powered by dotNetBB v2.42EC SP3 dotNetBB © 2000-2023 |
|
|