📄 mpdringview.cpp
字号:
// MPDRingView.cpp : implementation of the CMPDRingView class//#include "stdafx.h"#include "MPDRing.h"#include "MPDRingDoc.h"#include "MPDRingView.h"#include "AccountPasswordDlg.h"#include "MakeRingDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CMPDRingViewIMPLEMENT_DYNCREATE(CMPDRingView, CFormView)BEGIN_MESSAGE_MAP(CMPDRingView, CFormView) //{{AFX_MSG_MAP(CMPDRingView) ON_WM_SIZE() ON_BN_CLICKED(IDC_ENTER_BTN, OnEnterBtn) ON_BN_CLICKED(IDC_QUIT_BTN, OnQuitBtn) ON_COMMAND(ID_APP_CREATE_RING, OnCreateRing) ON_COMMAND(ID_APP_DESTROY_RING, OnDestroyRing) //}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CMPDRingView construction/destructionCMPDRingView::CMPDRingView() : CFormView(CMPDRingView::IDD){ //{{AFX_DATA_INIT(CMPDRingView) m_input = _T(""); //}}AFX_DATA_INIT m_bRectsValid = false; m_hProcess = NULL; m_hStdinPipeW = NULL;}CMPDRingView::~CMPDRingView(){}void CMPDRingView::DoDataExchange(CDataExchange* pDX){ CFormView::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMPDRingView) DDX_Control(pDX, IDC_QUIT_BTN, m_quit_btn); DDX_Control(pDX, IDC_OUTPUT_LIST, m_list); DDX_Control(pDX, IDC_INPUT_BOX, m_input_box); DDX_Control(pDX, IDC_ENTER_BTN, m_enter_btn); DDX_Text(pDX, IDC_INPUT_BOX, m_input); //}}AFX_DATA_MAP}BOOL CMPDRingView::PreCreateWindow(CREATESTRUCT& cs){ return CFormView::PreCreateWindow(cs);}void CMPDRingView::OnInitialUpdate(){ CFormView::OnInitialUpdate(); GetParentFrame()->RecalcLayout(); ResizeParentToFit(); GetClientRect(&m_rDialog); ClientToScreen(&m_rDialog); CMakeRingDlg rDlg; if (rDlg.DoModal() == IDOK) { m_input = rDlg.m_pszHosts; } else ExitProcess(1); CAccountPasswordDlg dlg; dlg.m_account = ""; while (dlg.m_account.GetLength() == 0) { if (dlg.DoModal() == IDOK) { if (dlg.m_account.GetLength() > 0) { if (dlg.m_password.GetLength() == 0) { if (MessageBox("Are you sure you want to enter a blank password?", "Empty field", MB_YESNO) == IDYES) StartMPDs(dlg.m_account, dlg.m_password); else dlg.m_account = ""; } else StartMPDs(dlg.m_account, dlg.m_password); } } else ExitProcess(0); } m_list.GetWindowRect(&m_rList); m_rList.left = m_rList.left - m_rDialog.left; m_rList.top = m_rList.top - m_rDialog.top; m_rList.right = m_rList.right - m_rDialog.right; m_rList.bottom = m_rList.bottom - m_rDialog.bottom; //CString str; //RECT r; //r = m_rList; str.Format("m_rList: (%d,%d) (%d,%d)", r.left, r.right, r.top, r.bottom); MessageBox(str, "m_rList"); m_enter_btn.GetWindowRect(&m_rEnter); m_rEnter.left = m_rEnter.left - m_rDialog.right; m_rEnter.right = m_rEnter.right - m_rDialog.right; m_rEnter.top = m_rEnter.top - m_rDialog.bottom; m_rEnter.bottom = m_rEnter.bottom - m_rDialog.bottom; //r = m_rEnter; str.Format("m_rEnter: (%d,%d) (%d,%d)", r.left, r.right, r.top, r.bottom); MessageBox(str, "m_rEnter"); m_input_box.GetWindowRect(&m_rInput); m_rInput.left = m_rInput.left - m_rDialog.left; m_rInput.right = m_rInput.right - m_rDialog.right; m_rInput.top = m_rInput.top - m_rDialog.bottom; m_rInput.bottom = m_rInput.bottom - m_rDialog.bottom; //r = m_rInput; str.Format("m_rInput: (%d,%d) (%d,%d)", r.left, r.right, r.top, r.bottom); MessageBox(str, "m_rInput"); m_quit_btn.GetWindowRect(&m_rQuit); m_rQuit.left = m_rQuit.left - m_rDialog.right; m_rQuit.right = m_rQuit.right - m_rDialog.right; m_rQuit.top = m_rQuit.top - m_rDialog.bottom; m_rQuit.bottom = m_rQuit.bottom - m_rDialog.bottom; //r = m_rQuit; str.Format("m_rQuit: (%d,%d) (%d,%d)", r.left, r.right, r.top, r.bottom); MessageBox(str, "m_rQuit"); m_bRectsValid = true; CMPDRingDoc *pDoc = GetDocument(); pDoc->SetTitle("Connected");}/////////////////////////////////////////////////////////////////////////////// CMPDRingView diagnostics#ifdef _DEBUGvoid CMPDRingView::AssertValid() const{ CFormView::AssertValid();}void CMPDRingView::Dump(CDumpContext& dc) const{ CFormView::Dump(dc);}CMPDRingDoc* CMPDRingView::GetDocument() // non-debug version is inline{ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMPDRingDoc))); return (CMPDRingDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CMPDRingView message handlersvoid CMPDRingView::OnSize(UINT nType, int cx, int cy) { //CFormView::OnSize(nType, cx, cy); if (m_bRectsValid) { RECT r; //CString str; GetClientRect(&m_rDialog); r.left = m_rDialog.left + m_rList.left; r.right = m_rDialog.right + m_rList.right; r.top = m_rDialog.top + m_rList.top; r.bottom = m_rDialog.bottom + m_rList.bottom; m_list.MoveWindow(&r); //str.Format("m_rList: (%d,%d) (%d,%d)", r.left, r.right, r.top, r.bottom); MessageBox(str, "m_rList"); r.left = m_rDialog.right + m_rEnter.left; r.right = m_rDialog.right + m_rEnter.right; r.top = m_rDialog.bottom + m_rEnter.top; r.bottom = m_rDialog.bottom + m_rEnter.bottom; m_enter_btn.MoveWindow(&r); //str.Format("m_rEnter: (%d,%d) (%d,%d)", r.left, r.right, r.top, r.bottom); MessageBox(str, "m_rEnter"); r.left = m_rDialog.left + m_rInput.left; r.right = m_rDialog.right + m_rInput.right; r.top = m_rDialog.bottom + m_rInput.top; r.bottom = m_rDialog.bottom + m_rInput.bottom; m_input_box.MoveWindow(&r); //str.Format("m_rInput: (%d,%d) (%d,%d)", r.left, r.right, r.top, r.bottom); MessageBox(str, "m_rInput"); r.left = m_rDialog.right + m_rQuit.left; r.right = m_rDialog.right + m_rQuit.right; r.top = m_rDialog.bottom + m_rQuit.top; r.bottom = m_rDialog.bottom + m_rQuit.bottom; m_quit_btn.MoveWindow(&r); //str.Format("m_rQuit: (%d,%d) (%d,%d)", r.left, r.right, r.top, r.bottom); MessageBox(str, "m_rQuit"); }}struct RedirectOutputThreadArg{ HWND hWnd; HANDLE hPipe;};void RedirectOutputThread(RedirectOutputThreadArg *pArg){ DWORD dwNumRead; char buffer[1024]; HANDLE hPipe; HWND hWnd; hPipe = pArg->hPipe; hWnd = pArg->hWnd; delete pArg; COPYDATASTRUCT copyData; while (ReadFile(hPipe, buffer, 1024, &dwNumRead, NULL)) { copyData.dwData = 0; copyData.cbData = dwNumRead; copyData.lpData = buffer; SendMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)©Data); } PostMessage(hWnd, WM_USER+1, 0, 0);}void CMPDRingView::StartMPDs(LPCTSTR pszAccount, LPCTSTR pszPassword){ BOOL bSuccess = FALSE; HANDLE hStdin, hStdout, hStderr; HANDLE hStdinPipeR=NULL; HANDLE hStdoutPipeR=NULL; HANDLE hStdoutPipeW=NULL; HANDLE hTempPipe=NULL; STARTUPINFO saInfo; PROCESS_INFORMATION psInfo; int nError; char pszCmdLine[4096]; sprintf(pszCmdLine, "mpd.exe -timeout %d -hosts %s", 10000, m_input); m_input = ""; UpdateData(FALSE); // Don't handle errors, just let the process die. // In the future this will be configurable to allow various debugging options. //SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); // Save stdin, stdout, and stderr hStdin = GetStdHandle(STD_INPUT_HANDLE); hStdout = GetStdHandle(STD_OUTPUT_HANDLE); hStderr = GetStdHandle(STD_ERROR_HANDLE); if (hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE || hStderr == INVALID_HANDLE_VALUE) { nError = GetLastError(); return; } // Set the security attributes to allow handles to be inherited SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.lpSecurityDescriptor = NULL; saAttr.bInheritHandle = TRUE; // Create pipes for stdin, stdout, and stderr // Stdout if (!CreatePipe(&hTempPipe, &hStdoutPipeW, &saAttr, 0)) { nError = GetLastError(); goto CLEANUP; } // Make the read end of the stdout pipe not inheritable if (!DuplicateHandle(GetCurrentProcess(), hTempPipe, GetCurrentProcess(), &hStdoutPipeR, 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { nError = GetLastError(); goto CLEANUP; } // Stdin if (!CreatePipe(&hStdinPipeR, &hTempPipe, &saAttr, 0)) { nError = GetLastError(); goto CLEANUP; } // Make the write end of the stdin pipe not inheritable if (!DuplicateHandle(GetCurrentProcess(), hTempPipe, GetCurrentProcess(), &m_hStdinPipeW, 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { nError = GetLastError(); goto CLEANUP; } // Set stdin, stdout, and stderr to the ends of the pipe the created process will use if (!SetStdHandle(STD_INPUT_HANDLE, hStdinPipeR)) { nError = GetLastError(); goto CLEANUP; } if (!SetStdHandle(STD_OUTPUT_HANDLE, hStdoutPipeW)) { nError = GetLastError(); goto RESTORE_CLEANUP; } if (!SetStdHandle(STD_ERROR_HANDLE, hStdoutPipeW)) { nError = GetLastError(); goto RESTORE_CLEANUP; } // Set up the STARTINFO structure memset(&saInfo, 0, sizeof(STARTUPINFO)); saInfo.cb = sizeof(STARTUPINFO); saInfo.hStdInput = hStdinPipeR; saInfo.hStdOutput = hStdoutPipeW; saInfo.hStdError = hStdoutPipeW; saInfo.dwFlags = STARTF_USESTDHANDLES; // Create the mpd process if (CreateProcess( NULL, pszCmdLine, NULL, NULL, TRUE, //DETACHED_PROCESS | IDLE_PRIORITY_CLASS, //CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS, CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP, //DETACHED_PROCESS | IDLE_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP, //CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS | CREATE_SUSPENDED, NULL, NULL, &saInfo, &psInfo)) { CloseHandle(psInfo.hThread); bSuccess = TRUE; } else { nError = GetLastError(); //Translate_Error(*nError, error_msg, L"LaunchProcess:CreateProcessAsUser failed: "); }RESTORE_CLEANUP: // Restore stdin, stdout, stderr if (!SetStdHandle(STD_INPUT_HANDLE, hStdin)) { nError = GetLastError(); } if (!SetStdHandle(STD_OUTPUT_HANDLE, hStdout)) { nError = GetLastError(); } if (!SetStdHandle(STD_ERROR_HANDLE, hStderr)) { nError = GetLastError(); }CLEANUP: CloseHandle(hStdoutPipeW); CloseHandle(hStdinPipeR); if (bSuccess) { RedirectOutputThreadArg *pArg = new RedirectOutputThreadArg; pArg->hPipe = hStdoutPipeR; pArg->hWnd = m_hWnd; DWORD dwThreadID; m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RedirectOutputThread, pArg, 0, &dwThreadID); DWORD dwNumWritten; char pBuffer[256]; sprintf(pBuffer, "%s\n%s\n", pszAccount, pszPassword); WriteFile(m_hStdinPipeW, pBuffer, strlen(pBuffer), &dwNumWritten, NULL); } m_hProcess = psInfo.hProcess;}LRESULT CMPDRingView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_COPYDATA) { COPYDATASTRUCT *pData = (COPYDATASTRUCT *)lParam; if (lParam) { UpdateData(); /* char c; CString str = ""; for (unsigned int i=0; i<pData->cbData; i++) { c = ((char*)pData->lpData)[i]; if (c == '\r' || c == '\n') { if (i < pData->cbData-1) { c = ((char*)pData->lpData)[i+1]; if (c == '\r' || c == '\n') i++; } //MessageBox("adding LF CR"); m_output += str + '\r' + '\n'; } else m_output += c; } //*/ char *pString = new char[pData->cbData]; memcpy(pString, pData->lpData, pData->cbData); char c; CString str = ""; for (unsigned int i=0; i<pData->cbData; i++) { c = ((char*)pData->lpData)[i]; if (c == '\r' || c == '\n' || i == (pData->cbData-1) ) { if (c != '\r' && c != '\n') str += c; if (i < pData->cbData-1) { c = ((char*)pData->lpData)[i+1]; if (c == '\r' || c == '\n') i++; } m_list.InsertString(-1, str); m_list.SetCurSel(m_list.GetCount()-1); str = ""; } else str += c; } UpdateData(FALSE); } } if (message == WM_USER+1) { UpdateData(); m_list.InsertString(-1, "The mpds have exited"); m_list.SetCurSel(m_list.GetCount()-1); CloseHandle(m_hStdinPipeW); m_hStdinPipeW = NULL; CloseHandle(m_hProcess); m_hProcess = NULL; UpdateData(FALSE); CMPDRingDoc *pDoc = GetDocument(); pDoc->SetTitle("Disconnected"); } return CFormView::WindowProc(message, wParam, lParam);}void CMPDRingView::OnEnterBtn() { DWORD dwNumWritten; bool bQuit = false; UpdateData(); if (m_input.CompareNoCase("quit") == 0 || m_input.CompareNoCase("exit") == 0) bQuit = true; m_list.InsertString(-1, m_input); m_list.SetCurSel(m_list.GetCount()-1); //m_output += m_input + '\r' + '\n'; m_input += '\n'; UpdateData(FALSE); WriteFile(m_hStdinPipeW, m_input.GetBuffer(0), m_input.GetLength(), &dwNumWritten, NULL); m_input = ""; UpdateData(FALSE); if (bQuit) PostMessage(WM_QUIT);}void CMPDRingView::OnQuitBtn() { if (m_hStdinPipeW != NULL) { /* DWORD dwNumWritten; CString str; str = "quit\n"; WriteFile(m_hStdinPipeW, str.GetBuffer(0), str.GetLength(), &dwNumWritten, NULL); FlushFileBuffers(m_hStdinPipeW); //*/ m_input = "quit"; UpdateData(FALSE); OnEnterBtn(); //Sleep(200); WaitForSingleObject(m_hThread, 3000); } PostMessage(WM_QUIT);}void CMPDRingView::StopMPDs(){ if (m_hProcess != NULL && m_hStdinPipeW != NULL) { DWORD dwNumWritten; CString str = "quit\n"; WriteFile(m_hStdinPipeW, str.GetBuffer(0), str.GetLength(), &dwNumWritten, NULL); FlushFileBuffers(m_hStdinPipeW); //CloseHandle(m_hStdinPipeW); //m_hStdinPipeW = NULL; //WaitForSingleObject(m_hProcess, 5000); //WaitForSingleObject(m_hThread, 5000); }}void CMPDRingView::OnCreateRing() { CMPDRingDoc *pDoc = GetDocument(); pDoc->SetTitle("Disconnected"); m_list.ResetContent(); StopMPDs(); CMakeRingDlg rDlg; if (rDlg.DoModal() == IDOK) { m_input = rDlg.m_pszHosts; } else return; CAccountPasswordDlg dlg; dlg.m_account = ""; while (dlg.m_account.GetLength() == 0) { if (dlg.DoModal() == IDOK) { if (dlg.m_account.GetLength() > 0) { if (dlg.m_password.GetLength() == 0) { if (MessageBox("Are you sure you want to enter a blank password?", "Empty field", MB_YESNO) == IDYES) StartMPDs(dlg.m_account, dlg.m_password); else dlg.m_account = ""; } else StartMPDs(dlg.m_account, dlg.m_password); } } else return; } pDoc->SetTitle("Connected");}void CMPDRingView::OnDestroyRing() { CMPDRingDoc *pDoc = GetDocument(); m_list.ResetContent(); StopMPDs(); pDoc->SetTitle("Disconnected");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -