⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vis_spectrum.cpp

📁 mp3 频谱分析源码, mp3播放器开发必备源码,
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	case WM_PAINT:
	{
		// just update the current display
		PAINTSTRUCT ps;
		RECT Rect;
		GetWindowRect(hWnd,&Rect);
		HDC hDC;
		hDC = BeginPaint(hWnd,&ps);
		// use stretchblt incase of doublesize
		StretchBlt(hDC,0,0,Rect.right - Rect.left, Rect.bottom - Rect.top,Plugin.hMemDC,0,0,STD_WIDTH,STD_HEIGHT,SRCCOPY);
		EndPaint(hWnd,&ps);
		return 0;
	}
	case WM_CHAR:
		switch(wParam) {
		// check for esc key
		case VK_ESCAPE:
			SendMessage(hWnd,WM_COMMAND,ID_CLOSEPLUGIN,0);
			break;
		default:
			SendMessage(Plugin.hWndParent,uMsg,wParam,lParam);
			return DefWindowProc(hWnd,uMsg,wParam,lParam);	
		}
	case WM_COMMAND:
		switch(LOWORD(wParam)) {
		case ID_CLOSEPLUGIN:
			SendMessage(hWnd,WM_CLOSE,0,0);
			break;
		case ID_CONFIG:
			PostMessage(Plugin.hWndParent,WM_COMMAND,40221,0);
			break;
		case ID_ABOUT:
			ShowWindow(CreateDialog(reinterpret_cast<HINSTANCE>(GetWindowLong(hWnd,GWL_HINSTANCE)),MAKEINTRESOURCE(IDD_ABOUTDLG),hWnd,AboutDlgProc),SW_SHOW);
			break;
		default:
			return DefWindowProc(hWnd,uMsg,wParam,lParam);	
		}
		break;
	case WM_DESTROY:	
	{
		if(Plugin.Settings.bSaveWndPos) {
			RECT rect;
			char* szFileName = new char[256];
			GetConfigFileName(&waModule,szFileName,256);
			GetWindowRect(hWnd,&rect);
			Plugin.Settings.ulLeft = rect.left;
			Plugin.Settings.ulTop = rect.top;
			WritePrivateProfileInt(PLUGIN_KEY,"ulLeft",Plugin.Settings.ulLeft,szFileName);
			WritePrivateProfileInt(PLUGIN_KEY,"ulTop",Plugin.Settings.ulTop,szFileName);
			delete[] szFileName;
			// restore the original window procedure
			SetWindowLong(Plugin.hWndParent,GWL_WNDPROC,(long)WndProcOld);
		}
		PostQuitMessage(0);
		break;
	}
	default:
		return DefWindowProc(hWnd,uMsg,wParam,lParam);
	}
	return 0;
}

// Updates the rectangle and take into account the fact that
// it may be in doublesize mode.
void UpdateRect(LPRECT lpRect, HWND hWnd)
{
	HDC hDC = GetDC(hWnd);
	if(!Plugin.Settings.bDoubleSize) {
		// update a cirtain rectangle on the window
		BitBlt(hDC,lpRect->left,lpRect->top,lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, Plugin.hMemDC,lpRect->left,lpRect->top,SRCCOPY);
	}
	else {
		StretchBlt(hDC,lpRect->left*2,lpRect->top*2,(lpRect->right - lpRect->left)*2, (lpRect->bottom - lpRect->top)*2, Plugin.hMemDC,lpRect->left,lpRect->top,lpRect->right - lpRect->left,lpRect->bottom - lpRect->top,SRCCOPY);
	}
	ReleaseDC(hWnd,hDC);
}

// The same as the windows function PtInRect only it takes into
// account the fact that the window may be in doublesize mode.
bool PointInRect(LPRECT lpRect, POINT& pt) 
{
	if(!Plugin.Settings.bDoubleSize) {
		if(pt.x >= lpRect->left && pt.x <= lpRect->right && pt.y >= lpRect->top && pt.y <=lpRect->bottom) 
			return true;
	}
	else {
		if(pt.x >= lpRect->left*2 && pt.x <= lpRect->right*2 && pt.y >= lpRect->top*2 && pt.y <= lpRect->bottom*2)
			return true;
	}
	return false;
}


// Subclass callback for winamp so we can detect when the stop
// button is clicked or when the end of file is reached or whatever.
// Any funny bits not in the winamp api documentation (such as
// hidden messages or whatever) were found with Spy++.

// -- Note: Someone please find a stable method of subclassing the winamp
// window. I must be missing something.
LRESULT CALLBACK SubWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if(uMsg==WM_COMMAND) {
		switch(LOWORD(wParam)) {
		case PLUGIN_TOGGLE:
			// Prevents winamp from crashing when you close the plugin
			PostMessage(Plugin.hWndMain,WM_CLOSE,0,0);
			return 0;
		case WINAMP_BUTTON2: // otherwise known as play
			// if an effect is on, stop it.
			KillUpdateThread();
			break;
		case WINAMP_BUTTON3: // otherwise known as pause
			// drop the bars down, EFFECT_WAVE is not perfect, do not use.
			InitUpdateThread(EFFECT_DROP);
			break;
		case WINAMP_BUTTON1: // skip back
		case WINAMP_BUTTON5: // skip forward
			// make sure that no effects are on
			KillUpdateThread();
			break;
		case WINAMP_BUTTON4: { // the stop button
			// drop the bars down
			InitUpdateThread(EFFECT_DROP);	
			}
		} // end of switch
	}
	else if(uMsg==WM_COPYDATA) {
		COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
		// code for opening a new file
		if(pcds->dwData == WINAMP_PLAYFILE) {
			// kill the effect thread as we are now playing
			KillUpdateThread();
		}
	}
	else if(uMsg==WM_CLOSE) {
		if(IsWindow(Plugin.hWndMain)) {
			PostMessage(Plugin.hWndMain,WM_CLOSE,0,0);
			PostMessage(Plugin.hWndParent,WM_CLOSE,0,0);
		}
		return 0;
	}
	else if(uMsg==WM_SYSCOMMAND) {
		if(wParam == 0x00009D00 && lParam == 0x00010000) {
			// this is when ctrl+shift+k is pressed
			PostMessage(Plugin.hWndMain,WM_CLOSE,0,0);
			// if you call the winamp window procedure it
			// fucks up so just return instead.
			return 0;
		}
	}
	else if(uMsg==WM_USER+2) {
		// end of file:
		InitUpdateThread(EFFECT_DROP);
	}
	// Fixme: Get winamp to dock with us and get our window to move if
	// docked with winamp.
	/*else if(uMsg==WM_WINDOWPOSCHANGING) {
		LPWINDOWPOS lpWndPos = reinterpret_cast<LPWINDOWPOS>(lParam);
		RECT rcMe;
		GetWindowRect(Plugin.hWndMain,&rcMe);
		rect_list_dock(hWnd,&lpWndPos->x,&lpWndPos->y,Plugin.Settings.ulWindowSnap,&rcMe,1);
	}*/
	 //call the original window procedure
	return CallWindowProc((WNDPROC)WndProcOld,hWnd,uMsg,wParam,lParam);
}


// This thread function will create a drop effect on the bars
// if it is called and at the same time, update the main window.
// It is used when winamp is stopped or paused.
DWORD APIENTRY UpdateThread(LPVOID lpParam)
{
	int nFunc = ((int)lpParam);

	switch(nFunc) {
	case EFFECT_DROP:
	{
		for(int i=0;i<576;i++) {
			waModule.spectrumData[0][i] = 0;
		}
		for(i=0;i<255 && !kill_update_thread;i++) {
			Sleep(waModule.delayMs);
			OnPluginRender(&waModule);
		}
		PostMessage(Plugin.hWndMain,WM_USER,0,USR_CLOSETHREAD);
		break;
	}
	case EFFECT_WAVE:
	{
		bool bFilterMap = Plugin.Settings.bFilter;

		Plugin.Settings.bFilter = true;
		
		
		for(int i=0;i<576;i++) {
			waModule.spectrumData[0][i] = 0;
			g_achDisplayData[i] = 0;
		}
		
		bool bForward = true;
		while(!kill_update_thread) {
			
			if(bForward) {
				for(int i=0;i<256/Plugin.Settings.uchBarWidth && !kill_update_thread;i++) {
					if(g_achDisplayData[i] > 0) g_achDisplayData[i] = 0;
					Sleep(waModule.delayMs*2);
					
					g_achScreenData[i] = 255;
					g_achPeakData[0][i] = 255;
					
					OnPluginRender(&waModule);

					for(int j=0;j<Plugin.Settings.uchBarWidth;j++) {
						Sleep(waModule.delayMs/2);
						OnPluginRender(&waModule);
					}
					
					
				}
				bForward = false;
			}
			else {
				for(int i=(256/Plugin.Settings.uchBarWidth)-1;i>=0 && !kill_update_thread;i--) {
					if(g_achDisplayData[i] > 0) g_achDisplayData[i] = 0;
					Sleep(waModule.delayMs*2);
					
					
					g_achScreenData[i] = 255;
					
					g_achPeakData[0][i] = 255;
					
					
					OnPluginRender(&waModule);

					for(int j=0;j<Plugin.Settings.uchBarWidth;j++) {
						Sleep(waModule.delayMs/2);
						OnPluginRender(&waModule);
					}
				}
				bForward = true;
			}
		}
		Plugin.Settings.bFilter = bFilterMap;
		break;
	}
	default:
		break;
	}
	return 0;
}


void KillUpdateThread()
{
	if(!hThread) return;
	kill_update_thread = 1;

	if (WaitForSingleObject(hThread,INFINITE) == WAIT_TIMEOUT)
	{
		TerminateThread(hThread,0);
	}
	
	if(hThread) CloseHandle(hThread);
	hThread = NULL;
	kill_update_thread = 0;
}

void InitUpdateThread(int nFunc)
{
	DWORD dwID;
	if(hThread) return;
	kill_update_thread = 0;
	hThread = CreateThread(NULL,0,UpdateThread,(LPVOID)nFunc,0,&dwID);
}

BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg) {
	case WM_INITDIALOG:
		g_bAboutActive = true;
		break;
	case WM_COMMAND:
	{
		switch(LOWORD(wParam)) {
		case IDOK:
		case IDCANCEL:
			g_bAboutActive = false;
			EndDialog(hDlg,LOWORD(wParam));
			break;
		}
		return FALSE;
	}
	default:
		return FALSE;
	}
	return TRUE;
}

// Read in bar colour mappings from the skin bitmap. Also gets
// grid colour ,peak colour and background colour.
void GetColourMap()
{
	
	HDC hDC = CreateCompatibleDC(NULL);
	HGDIOBJ hOld = SelectObject(hDC,Plugin.hBmpSkin);

	for(int i=0;i<256;i++) {
		g_ulColourMap[i] = GetPixel(hDC,(255-(i))+18,144);
	}

	g_ulPeakColour = GetPixel(hDC,274,144);
	g_ulBackColour = GetPixel(hDC,274,145);
	g_ulGridColour = GetPixel(hDC,273,145);

	SelectObject(hDC, hOld);
	DeleteDC(hDC);
}

bool SetCurrentSkin(const char* lpszBitmap)
{
	DeleteObject(Plugin.hBmpSkin);
	if(lpszBitmap!=NULL) {
		Plugin.hBmpSkin = (HBITMAP)LoadImage(NULL,lpszBitmap,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
		if(!Plugin.hBmpSkin) Plugin.hBmpSkin = LoadBitmap(waModule.hDllInstance,MAKEINTRESOURCE(IDB_BMPSKIN));
	}
	else {
		Plugin.hBmpSkin = LoadBitmap(waModule.hDllInstance,MAKEINTRESOURCE(IDB_BMPSKIN));
	}
		BitmapBltEx(Plugin.hMemDC, Plugin.hBmpSkin,0,0,STD_WIDTH,STD_HEIGHT,0,0);
	GetColourMap();
	// if dim titles then make it appear dimmed if in settings
	
	if(Plugin.Settings.bDimTitleBar) {
		if(Plugin.bInConfig) {
			BitmapBltEx(Plugin.hMemDC, Plugin.hBmpSkin, 0, 0, 275, 14, 0, 130);
		}
	}

	
	// update the window
	SendMessage(Plugin.hWndMain,WM_USER,0,USR_REDRAWWINDOW);

	return true;
}

void LoadSkin()
{
	char* FileName = new char[256];
	char* skin = new char[256];
	GetConfigFileName(&waModule,FileName,256);
	GetPrivateProfileString(PLUGIN_KEY,"skin",0,skin,256,FileName);
	SetCurrentSkin(skin);
	delete[] skin;
	delete[] FileName;
}

void SaveSkin(char* szName)
{
	char* FileName = new char[256];
	char* skin = new char[256];
	GetConfigFileName(&waModule,FileName,256);
	WritePrivateProfileString(PLUGIN_KEY,"skin",szName,FileName);
	SetCurrentSkin(skin);
	delete[] skin;
	delete[] FileName;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -