VC动态生成菜单菜单响应及加速键的使用

VC动态生成菜单菜单响应及加速键的使用

一、使用环境

    本文讲解的使用环境为MFC 的Visual Studio项目的单文档应用程序类型,字符集使用多字节字符集,对话框和多文档应用程序类型稍有不同这里不再讲解说明。


二、读取XML树形结构菜单

本文的上一节已经详细讲解了使用pugixml读取XML树形结构菜单的内容,这里不再重复直接使用。

    (1)在CMainFrame类的头文件MainFrm.h中添加树形结构菜单存储结构

public:

//可点击菜单ID 名称 命令 是否使用加速键

typedef struct _CMDINFO

{

UINT nID; //ID

CString strName;    //名称

CString strCmd; //命令

bool bAccelkey; //是否使用加速键

_CMDINFO()

{

nID = 0;

strName = "";

strCmd = "";

bAccelkey = false;

}

}CMDINFO, *LPCMDINFO;

private:

//菜单树结构头指针

TS_PMENUNODE m_ptrMenuNode;

//可点击菜单信息

vector<CMDINFO> m_vCmdInfo;

//菜单ID累加存储临时变量

int m_nMenuID;

public:

//菜单ID结束数值

static int m_nMenuIDEnd;

   (2)在MainFrm.cpp源文件顶部添加起始菜单ID常量定义和声明菜单ID结束数值定义

#define m_nMenuIDStart  1000

int CMainFrame::m_nMenuIDEnd = m_nMenuIDStart;

   (3)在CMainFrame类的构造函数CMainFrame()中添加读取XML树形结构菜单代码,我们的菜单配置XML为menu.xml放置到程序exe所在目录下:

m_ptrMenuNode = new TS_MENUNODE();

char szFullPath[256];

ZeroMemory(szFullPath, 256);

::GetModuleFileName(NULL, szFullPath, 256);

(_tcsrchr(szFullPath, _T('\\')))[1] = 0;//删除文件名,只获得路径 字串

CString strPath = szFullPath;

strPath += "menu.xml";

CKernelXml KernelXml;

int num = KernelXml.GetMenuXml(strPath, m_ptrMenuNode);

m_nMenuIDEnd = m_nMenuIDStart;

m_nMenuIDEnd += (num - 1); 

三、动态创建菜单

  (1)在CMainFrame类的LoadFrame函数最后添加菜单创建代码:

///////////////////////动态生成菜单//////////////////////

CMenu *pMenu = CMenu::FromHandle(m_wndMenuBar.GetDefaultMenu());

//清空原有的菜单栏

int num = pMenu->GetMenuItemCount();

for (int i=num-1;i>=0;i--)

{

pMenu->DeleteMenu(i, MF_BYPOSITION);

}

//动态添加菜单

m_nMenuID = m_nMenuIDStart;

vector<CMenu *> pHMenu;

//迭代添加菜单

CreateMenuChildrenNode(pMenu, m_ptrMenuNode, pHMenu);

m_wndMenuBar.CreateFromMenu(pMenu->GetSafeHmenu(), TRUE, TRUE);

int count = pHMenu.size();

for (int i=0;i<count;i++)

{

if (NULL!=pHMenu[i])

{

delete pHMenu[i];

pHMenu[i] = NULL;

}

}

pHMenu.clear();

return TRUE;

(2)上面代码中用到的CreateMenuChildrenNode函数,请在CmainFrame类的头文件中声明,并在CmainFrame类的源文件中定义:

private:

bool CreateMenuChildrenNode(CMenu *pMenu, TS_PMENUNODE &pMenuNode, vector<CMenu *> &pHMenu);


bool CMainFrame::CreateMenuChildrenNode(CMenu *pMenu, TS_PMENUNODE &pMenuNode, vector<CMenu *> &pHMenu)

{

bool ret = false;

int count = pMenuNode->ptrChildren.size();

for (int i = 0; i < count; i++)

{

CString strType = pMenuNode->ptrChildren[i]->strType.MakeUpper();

if ("POPUP" == strType)

{

//创建并添加

CMenu * hMenu = new CMenu();

hMenu->CreateMenu();

pMenu->AppendMenu(MF_POPUP, (UINT)(hMenu->m_hMenu), pMenuNode->ptrChildren[i]->strName);

pHMenu.push_back(hMenu);

CreateMenuChildrenNode(hMenu, pMenuNode->ptrChildren[i], pHMenu);

}

else if ("SEPARATOR" == strType)

{

//添加

pMenu->AppendMenu(MF_SEPARATOR);

}

else if ("STRING" == strType)

{

UINT nKey = MF_STRING;

if ("true" == pMenuNode->ptrChildren[i]->strChecked.Trim().MakeLower())

{

nKey = nKey | MF_CHECKED;

}

pMenu->AppendMenu(nKey, m_nMenuID, TEXT(pMenuNode->ptrChildren[i]->strName));

//菜单信息

CMDINFO cmdInfo;

cmdInfo.nID = m_nMenuID;

cmdInfo.strName = pMenuNode->ptrChildren[i]->strName;

cmdInfo.strCmd = pMenuNode->ptrChildren[i]->strCmd;

m_vCmdInfo.push_back(cmdInfo);

m_nMenuID++;

}

}

return true;

}

(3)至此我们的菜单及创建完毕


四、添加菜单响应

(1)在CMainFrame类的头文件 DECLARE_MESSAGE_MAP()宏上面添加菜单响应函数声明:

afx_msg void OnMenuItem(UINT id);

afx_msg void OnUpdateItem(CCmdUI *pCmdUI);

(2)在CMainFrame类的源文件的宏映射BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)和END_MESSAGE_MAP()中间添加菜单响应宏映射:

ON_COMMAND_RANGE(m_nMenuIDStart, CMainFrame::m_nMenuIDEnd, &CMainFrame::OnMenuItem)

ON_UPDATE_COMMAND_UI_RANGE(m_nMenuIDStart, CMainFrame::m_nMenuIDEnd, &CMainFrame::OnUpdateItem)

(3)在CMainFrame类的源文件中添加菜单响应函数定义:

void CMainFrame::OnUpdateItem(CCmdUI *pCmdUI)

{

int count = m_vCmdInfo.size();

for (int i = 0; i < count; i++)

{

if (pCmdUI->m_nID == m_vCmdInfo[i].nID)

{

//对应的CCmdUI的处理

if ("WJ_NEW_XM" == m_vCmdInfo[i].strCmd)

{


}

else if ("WJ_NEW_WZ" == m_vCmdInfo[i].strCmd)

{


}

//......................................

break;

}

}

}


void CMainFrame::OnMenuItem(UINT id)

{

int count = m_vCmdInfo.size();

for (int i = 0; i < count; i++)

{

if (id == m_vCmdInfo[i].nID)

{

//对应的菜单响应函数调用

if ("WJ_NEW_XM"==m_vCmdInfo[i].strCmd)

{


}

else if ("WJ_NEW_WZ" == m_vCmdInfo[i].strCmd)

{


}

//......................................

MessageBox(m_vCmdInfo[i].strName + ":" + m_vCmdInfo[i].strCmd);

break;

}

}

}

(4)至此菜单响应添加完毕:


五、加速键的添加

(1)在CMainFrame类的头文件 DECLARE_MESSAGE_MAP()宏上面添加加速键响应函数声明:

afx_msg LRESULT OnHotKey(WPARAM  wParam, LPARAM  lParam);

(2)在CMainFrame类的源文件的宏映射BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)和END_MESSAGE_MAP()中间添加加速键宏映射:

ON_MESSAGE(WM_HOTKEY, OnHotKey)

(3)在CMainFrame类的源文件中添加加速键响应函数定义:

LRESULT CMainFrame::OnHotKey(WPARAM  wParam, LPARAM  lParam)

{

int count = m_vCmdInfo.size();

for (int i = 0; i < count; i++)

{

if (wParam == m_vCmdInfo[i].nID)

{

//对应的菜单响应函数的加速键函数调用

if ("WJ_NEW_XM" == m_vCmdInfo[i].strCmd)

{


}

else if ("WJ_NEW_WZ" == m_vCmdInfo[i].strCmd)

{


}

//......................................

MessageBox(m_vCmdInfo[i].strName + " 加速键响应:" + m_vCmdInfo[i].strCmd);

break;

}

}

return 0;

}

(4)在CreateMenuChildrenNode函数的cmdInfo.strCmd = pMenuNode->ptrChildren[i]->strCmd;和m_vCmdInfo.push_back(cmdInfo);代码之间添加加速键的注册代码:

//判断是否有加速键

if (""!=pMenuNode->ptrChildren[i]->strAccelkey)

{

//注册加速键

vector <CString> vecString;

SplitCString(pMenuNode->ptrChildren[i]->strAccelkey,"|", vecString);

//MOD_ALT MOD_SHIFT MOD_WIN MOD_CONTROL MOD_NOREPEAT

int num = vecString.size();

nKey = 0;

for (int m = 0; m < num; m++)

{

CString UpString = vecString[m].Trim().MakeUpper();

if ("MOD_ALT" == UpString)

{

nKey = nKey | MOD_ALT;

}

else if ("MOD_SHIFT" == UpString)

{

nKey = nKey | MOD_SHIFT;

}

else if ("MOD_WIN" == UpString)

{

nKey = nKey | MOD_WIN;

}

else if ("MOD_CONTROL" == UpString)

{

nKey = nKey | MOD_CONTROL;

}

else if ("MOD_NOREPEAT" == UpString)

{

nKey = nKey | MOD_NOREPEAT;

}

}


UINT vk = 0;

if (1 == vecString[num - 1].Trim().GetLength())

{

//字母键时直接转义

vk = vecString[num - 1][0];

}

else

{

vk = GetCodeByName((LPTSTR)(LPCTSTR)vecString[num - 1].Trim());

}

RegisterHotKey(m_hWnd, m_nMenuID, nKey, vk);

cmdInfo.bAccelkey = true;

}

(5)字符串拆分函数SplitCString和由名称得到键值的转义函数GetCodeByName的实现:

    1、在CmainFrame类的头文件中声明,并在CmainFrame类的源文件中定义:

int SplitCString(CString strSource, CString strCh, vector <CString> &vecString);

UINT GetCodeByName(LPTSTR pszMsg);

int CMainFrame::SplitCString(CString strSource, CString strCh, vector <CString> &vecString)

{

int iPos = 0;

CString strTmp;

strTmp = strSource.Tokenize(strCh, iPos);

while (strTmp.Trim() != _T(""))

{

vecString.push_back(strTmp);

strTmp = strSource.Tokenize(strCh, iPos);

}

return 0;

}


UINT CMainFrame::GetCodeByName(LPTSTR pszMsg)

{

for (UINT i = 0; i < sizeof(msgInfo) / sizeof(CMainFrame::MSGINFO); i++)

{

if (lstrcmp(msgInfo[i].psz, pszMsg) == 0)

{

return msgInfo[i].msg;

}

}

return 0;

}

2、键值转义结构MSGINFO的声明和定义

 2.1、在CMianFrame类的头文件CMDINFO结构下方定义MSGINFO结构

typedef struct _MSGINFO {

UINT msg; //键值宏定义

LPTSTR psz; //键名

} MSGINFO, *LPMSGINFO;

  2.2、在CMianFrame类的源文件上方位置定义msgInfo

CMainFrame::MSGINFO msgInfo[] = {

{ VK_LBUTTON,TEXT("VK_LBUTTON") },

{ VK_RBUTTON,TEXT("VK_RBUTTON") },

{ VK_CANCEL, TEXT("VK_CANCEL") },

{ VK_MBUTTON,TEXT("VK_MBUTTON") },

{ VK_XBUTTON1, TEXT("VK_XBUTTON1") },

{ VK_XBUTTON2, TEXT("VK_XBUTTON2") },

{ VK_BACK,TEXT("VK_BACK") },

{ VK_TAB, TEXT("VK_TAB") },

{ VK_CLEAR,TEXT("VK_CLEAR") },

{ VK_RETURN,TEXT("VK_RETURN") },

{ VK_SHIFT,TEXT("VK_SHIFT") },

{ VK_CONTROL,TEXT("VK_CONTROL") },

{ VK_MENU,TEXT("VK_MENU") },

{ VK_PAUSE,TEXT("VK_PAUSE") },

{ VK_CAPITAL,TEXT("VK_CAPITAL") },

{ VK_KANA,TEXT("VK_KANA") },

{ VK_HANGEUL,TEXT("VK_HANGEUL") },

{ VK_HANGUL,TEXT("VK_HANGUL") },

{ VK_JUNJA,TEXT("VK_JUNJA") },

{ VK_FINAL,TEXT("VK_FINAL") },

{ VK_HANJA,TEXT("VK_HANJA") },

{ VK_KANJI, TEXT("VK_KANJI") },

{ VK_ESCAPE,TEXT("VK_ESCAPE") },

{ VK_CONVERT, TEXT("VK_CONVERT") },

{ VK_NONCONVERT, TEXT("VK_NONCONVERT") },

{ VK_ACCEPT,TEXT("VK_ACCEPT") },

{ VK_MODECHANGE, TEXT("VK_MODECHANGE") },

{ VK_SPACE,TEXT("VK_SPACE") },

{ VK_PRIOR, TEXT("VK_PRIOR") },

{ VK_NEXT,TEXT("VK_NEXT") },

{ VK_END,TEXT("VK_END") },

{ VK_HOME, TEXT("VK_HOME") },

{ VK_LEFT,TEXT("VK_LEFT") },

{ VK_UP, TEXT("VK_UP") },

{ VK_RIGHT,TEXT("VK_RIGHT") },

{ VK_DOWN,TEXT("VK_DOWN") },

{ VK_SELECT,TEXT("VK_SELECT") },

{ VK_PRINT, TEXT("VK_PRINT") },

{ VK_EXECUTE, TEXT("VK_EXECUTE") },

{ VK_SNAPSHOT, TEXT("VK_SNAPSHOT") },

{ VK_INSERT, TEXT("VK_INSERT") },

{ VK_DELETE,TEXT("VK_DELETE") },

{ VK_HELP,TEXT("VK_HELP") },

{ VK_LWIN,TEXT("VK_LWIN") },

{ VK_RWIN,TEXT("VK_RWIN") },

{ VK_APPS,TEXT("VK_APPS") },

{ VK_SLEEP,TEXT("VK_SLEEP") },

{ VK_NUMPAD0,TEXT("VK_NUMPAD0") },

{ VK_NUMPAD1,TEXT("VK_NUMPAD1") },

{ VK_NUMPAD2,TEXT("VK_NUMPAD2") },

{ VK_NUMPAD3,TEXT("VK_NUMPAD3") },

{ VK_NUMPAD4,TEXT("VK_NUMPAD4") },

{ VK_NUMPAD5,TEXT("VK_NUMPAD5") },

{ VK_NUMPAD6, TEXT("VK_NUMPAD6") },

{ VK_NUMPAD7,TEXT("VK_NUMPAD7") },

{ VK_NUMPAD8,TEXT("VK_NUMPAD8") },

{ VK_NUMPAD9, TEXT("VK_NUMPAD9") },

{ VK_MULTIPLY,TEXT("VK_MULTIPLY") },

{ VK_ADD,TEXT("VK_ADD") },

{ VK_SEPARATOR,TEXT("VK_SEPARATOR") },

{ VK_SUBTRACT,TEXT("VK_SUBTRACT") },

{ VK_DECIMAL,TEXT("VK_DECIMAL") },

{ VK_DIVIDE,TEXT("VK_DIVIDE") },

{ VK_F1,TEXT("VK_F1") },

{ VK_F2,TEXT("VK_F2") },

{ VK_F3,TEXT("VK_F3") },

{ VK_F4,TEXT("VK_F4") },

{ VK_F5,TEXT("VK_F5") },

{ VK_F6,TEXT("VK_F6") },

{ VK_F7,TEXT("VK_F7") },

{ VK_F8,TEXT("VK_F8") },

{ VK_F9,TEXT("VK_F9") },

{ VK_F10,TEXT("VK_F10") },

{ VK_F11,TEXT("VK_F11") },

{ VK_F12,TEXT("VK_F12") },

{ VK_F13,TEXT("VK_F13") },

{ VK_F14,TEXT("VK_F14") },

{ VK_F15,TEXT("VK_F15") },

{ VK_F16,TEXT("VK_F16") },

{ VK_F17,TEXT("VK_F17") },

{ VK_F18,TEXT("VK_F18") },

{ VK_F19,TEXT("VK_F19") },

{ VK_F20,TEXT("VK_F20") },

{ VK_F21,TEXT("VK_F21") },

{ VK_F22,TEXT("VK_F22") },

{ VK_F23,TEXT("VK_F23") },

{ VK_F24,TEXT("VK_F24") },

{ VK_NUMLOCK,TEXT("VK_NUMLOCK") },

{ VK_SCROLL,TEXT("VK_SCROLL") },

{ VK_OEM_NEC_EQUAL,TEXT("VK_OEM_NEC_EQUAL") },

{ VK_OEM_FJ_JISHO,TEXT("VK_OEM_FJ_JISHO") },

{ VK_OEM_FJ_MASSHOU,TEXT("VK_OEM_FJ_MASSHOU") },

{ VK_OEM_FJ_TOUROKU,TEXT("VK_OEM_FJ_TOUROKU") },

{ VK_OEM_FJ_LOYA,TEXT("VK_OEM_FJ_LOYA") },

{ VK_OEM_FJ_ROYA,TEXT("VK_OEM_FJ_ROYA") },

{ VK_LSHIFT,TEXT("VK_LSHIFT") },

{ VK_RSHIFT,TEXT("VK_RSHIFT") },

{ VK_LCONTROL,TEXT("VK_LCONTROL") },

{ VK_RCONTROL,TEXT("VK_RCONTROL") },

{ VK_LMENU,TEXT("VK_LMENU") },

{ VK_RMENU,TEXT("VK_RMENU") },

{ VK_BROWSER_BACK,TEXT("VK_BROWSER_BACK") },

{ VK_BROWSER_FORWARD,TEXT("VK_BROWSER_FORWARD") },

{ VK_BROWSER_REFRESH,TEXT("VK_BROWSER_REFRESH") },

{ VK_BROWSER_STOP,TEXT("VK_BROWSER_STOP") },

{ VK_BROWSER_SEARCH,TEXT("VK_BROWSER_SEARCH") },

{ VK_BROWSER_FAVORITES,TEXT("VK_BROWSER_FAVORITES") },

{ VK_BROWSER_HOME,TEXT("VK_BROWSER_HOME") },

{ VK_VOLUME_MUTE,TEXT("VK_VOLUME_MUTE") },

{ VK_VOLUME_DOWN,TEXT("VK_VOLUME_DOWN") },

{ VK_VOLUME_UP,TEXT("VK_VOLUME_UP") },

{ VK_MEDIA_NEXT_TRACK,TEXT("VK_MEDIA_NEXT_TRACK") },

{ VK_MEDIA_PREV_TRACK, TEXT("VK_MEDIA_PREV_TRACK") },

{ VK_MEDIA_STOP,TEXT("VK_MEDIA_STOP") },

{ VK_MEDIA_PLAY_PAUSE, TEXT("VK_MEDIA_PLAY_PAUSE") },

{ VK_LAUNCH_MAIL,TEXT("VK_LAUNCH_MAIL") },

{ VK_LAUNCH_MEDIA_SELECT,TEXT("VK_LAUNCH_MEDIA_SELECT") },

{ VK_LAUNCH_APP1,TEXT("VK_LAUNCH_APP1") },

{ VK_LAUNCH_APP2,TEXT("VK_LAUNCH_APP2") },

{ VK_OEM_1,TEXT("VK_OEM_1") },

{ VK_OEM_PLUS,TEXT("VK_OEM_PLUS") },

{ VK_OEM_COMMA,TEXT("VK_OEM_COMMA") },

{ VK_OEM_MINUS,TEXT("VK_OEM_MINUS") },

{ VK_OEM_PERIOD,TEXT("VK_OEM_PERIOD") },

{ VK_OEM_2,TEXT("VK_OEM_2") },

{ VK_OEM_3,TEXT("VK_OEM_3") },

{ VK_OEM_4, TEXT("VK_OEM_4") },

{ VK_OEM_5,TEXT("VK_OEM_5") },

{ VK_OEM_6,TEXT("VK_OEM_6") },

{ VK_OEM_7, TEXT("VK_OEM_7") },

{ VK_OEM_8, TEXT("VK_OEM_8") },

{ VK_OEM_AX,TEXT("VK_OEM_AX") },

{ VK_OEM_102, TEXT("VK_OEM_102") },

{ VK_ICO_HELP,TEXT("VK_ICO_HELP") },

{ VK_ICO_00,TEXT("VK_ICO_00") },

{ VK_PROCESSKEY,TEXT("VK_PROCESSKEY") },

{ VK_ICO_CLEAR,TEXT("VK_ICO_CLEAR") },

{ VK_PACKET,TEXT("VK_PACKET") },

{ VK_OEM_RESET,TEXT("VK_OEM_RESET") },

{ VK_OEM_JUMP,TEXT("VK_OEM_JUMP") },

{ VK_OEM_PA1,TEXT("VK_OEM_PA1") },

{ VK_OEM_PA2,TEXT("VK_OEM_PA2") },

{ VK_OEM_PA3,TEXT("VK_OEM_PA3") },

{ VK_OEM_WSCTRL,TEXT("VK_OEM_WSCTRL") },

{ VK_OEM_CUSEL,TEXT("VK_OEM_CUSEL") },

{ VK_OEM_ATTN,TEXT("VK_OEM_ATTN") },

{ VK_OEM_FINISH,TEXT("VK_OEM_FINISH") },

{ VK_OEM_COPY,TEXT("VK_OEM_COPY") },

{ VK_OEM_AUTO,TEXT("VK_OEM_AUTO") },

{ VK_OEM_ENLW,TEXT("VK_OEM_ENLW") },

{ VK_OEM_BACKTAB,TEXT("VK_OEM_BACKTAB") },

{ VK_ATTN, TEXT("VK_ATTN") },

{ VK_CRSEL,TEXT("VK_CRSEL") },

{ VK_EXSEL,TEXT("VK_EXSEL") },

{ VK_EREOF, TEXT("VK_EREOF") },

{ VK_PLAY, TEXT("VK_PLAY") },

{ VK_ZOOM,TEXT("VK_ZOOM") },

{ VK_NONAME,TEXT("VK_NONAME") },

{ VK_PA1,TEXT("VK_PA1") },

{ VK_OEM_CLEAR,TEXT("VK_OEM_CLEAR") }

};

(6)程序结束取消加速键的注册

用类向导给CMainFrame类添加WM_DESTORY消息的消息响应函数OnDestroy函数,在函数最后添加取消加速键的注册代码:

//取消注册加速键

int count = m_vCmdInfo.size();

for (int i = 0; i < count; i++)

{

if (m_vCmdInfo[i].bAccelkey)

{

UnregisterHotKey(m_hWnd, m_vCmdInfo[i].nID);

}

}

(7)至此我们的Visual Studio项目的单文档应用程序的动态生成菜单菜单响应及加速键的使用就全部完成了,谢谢大家的支持:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容