المساعدة - البحث - قائمة الأعضاء - التقويم
نسخة كاملة: برنامج محرر برايل العربي
برمجة - شبكات - كمبيوتر - منتديات الفريق العربي للبرمجة > منتديات لغات البرمجة العام > منتدى مبرمجي C و ++C و C++.NET > أرشيف منتدى قسم السي ++
bozoclown2000
السلام عليكم و رحمة الله و بركاته

أنا ضيف جديد على هذا الموقع و ما كنت لأعرف عن هذا الموقع لولا أنني وجدت تعليق الأخ هاني الاتاسي على موضوع قد طرحته من أكثر من ستة أشهر في أحد المنتديات المتخصصة بالحاسب

المهم لقد قمت بعمل برنامج أطلقت عليه اسم محرر برايل العربي يمكنكم القراءة عنه و معرفة هدفه من الموقع الذي قمت ببناءه خصيصا له و هو arabicbraille.cjb.net أو brailleeditor.cjb.net و قد استخدمت لغة الفيجول سي بلس بلس بدعم مكتبة ام اف سي .. و لكن هناك ضعف في دعم اللغة العربية خصوصا في الكتابة ..
و هناك مشلكة واجهتني و لم أتمكن من حلها حتى الآن و هو أنني كلما ضغطت على مفتاح Shift + CTRL التي على يمين أو يسار لوحة المفاتيح لتغيير اللغة تظهر لي رسالة خطأ .. و لم أتمكن حتى الآن من معرفة السبب .. فهل يمكنكم مساعدتي .. علما بأن هذا الخطأ يحدث عند اختيار خلق مستند عادي ..

شكرا لكم جميعاعلى هذا المنتدى الرائع

و السلام عليكم
هاني الأتاسي
السلام عليكم ،

أشكرك على تسجيلك في هذا المنتدى ، وإن شاء الله سوف تجد كل ماهو مفيد وتجد أجوبة لجميع تساؤلاتك في الفيجوال سي++ وغيرها من اللغات .. أيضا أشكرك على فكرة هذا البرنامج الرائع .

أولا ، لا أدري لماذا قمت بوضع نسخة الDebug عن البرنامج ولم تضع نسخة الRelease .. إن نسخة الDebug هي مخصصة فقط لوقت تطوير البرنامج أما وقت الإنتهاء فيجب أن تختار Release وتصنع ملف الexe . إن المترجم (الفيجوال سي) يضع بيانات تخص التنقيح ليس لها علاقة في البرنامج داخل ملف الexe ، وبالتالي يكبر حجم الملف بلا أي داعي ، فملفك الذي يبلغ حجمه 300كيلو سوف يتقلص إلى مادون 150كيلو . أيضا من أجل نسخة الDebug فلقد قمت أنت بتوزيع ملفات الDebug لجميع مكتبات الربط الديناميكي أي على سبيل المثال MFCO42D.DLL (وD في النهاية تعني Debug) . ومع العلم أني تجاهلت تنزيلهم في برنامج الإعداد لأنه عندي نسخ أخرى منهم مطورة أكثر وبالتالي لم يعمل برنامجك عندي ، وأيضا إن قمت أنابتنزيلهم فإن برنامج الفيجوال سي++ لدي لن يعمل بشكل جيد ..

الحل لهذه المشكلة عليك مباشرة أن تصنع نسخة Release من مشروعك كالتالي :
من قائمة Build إختر Set Active Configuration ومنه إختر Win32-Release .. والأن إذا قمت بإختيار Build أو F7 سوف تلاحظ أن الفيجوال سي قد أنشئ نسخة أخرى من برنامجك الexe أصغر حجما ومكتبات الربط التي توزع معها هي الصحيحة (MFC42.DLL) .

بالنسبة لمشكلة تغيير اللغة ، فعلا توجد مشكلة نبهتني عليها . قمت بتتبع المشكلة فوجدتها تحدث في الملف Wincore.cpp في السطر التالي :
((ASSERT(nID == 0 || ::IsWindow(hWndCtrl
لا أدري لماذا حتى الآن توجد المشكلة هنا ، ولكن بما أن ASSERT يلغى عملها في نسخة ال Release فسوف تجد أن رسالة الخطأ لن تظهر في حالة قمت بانشاء مشروعك على هيئة Release .

وأنا منتظر منك أن تبدل المشروع الحالي بمشروع ال Release حتى يعمل عندي وأجربه .. وإن شاء الله أجد حل جذري لهذه المشكلة غير هذا الحل الذي لا يجدي في نسخ الDebug ...
bozoclown2000
السلام عليكم و رحمة الله و بركاته

أولا ألف شكر لك أخ هاني على ترحيبك بي في موقعكم الأكثر من رائع .. و أتمنى أن نتعاون جميعا لتطوير مهاراتنا ... و الاستفادة من خبرة بعضنا البعض ..

ثانيا جزاك الله خيرا على التعليق الذي وضعته و سوف أقو بتجربته و الرد عليك في أقرب فرصة إن شاء الله

شاكرا و مقدرا لجهودك المباركة جعلها الله في موازين أعمالك
هاني الأتاسي
السلام عليكم،

أولا لكي لا نظلم ال MFC فإن مشكلة ال RichEdit لم تكن منها ، فعلى العكس تماما فال MFC هي التي كشفت عن الخلل الموجود في المكتبة Riched32.dll. وهي مكتبة مرفقة مع ويندوز مسؤولة عن ال RichEdit Control . المشكلة كانت في حالة تم قلب اللغة إلى العربي أو الإنجليزي باستخدام Ctrl+Shift . في الحقيقة ، عندما تقوم بعملية القلب فإن الأداة تقوم بإرسال رسالة WM_COMMAND من نوع Notification ذات قيمة EN_ALIGN_LTR أو EN_ALIGN_RTL وهما يكافئان القيمتان 0x710 و 0x711 .. ولكن الكود الذي يقوم بإرسال الرسالة إلى النافذة يقوم بتجهيز بارامترات الرسالة بشكل خاطئ ، حيث المفروض أن lParam تحتوي على قيمة handle النافذة صاحبة الnotification و الword العلوي من wParam يحتوي على رقم ال notify . ولكننا نجد أن رقم الnotify هو بالخطأ الجزء العلوي من lParam وهذا ما أدى إلى أن نحصل على رقم handle خاطئ ، وأدى هذا من الMFC في الملف Wincore.cpp من أن يظهر assertion في السطر التالي :
((ASSERT(nID == 0 || ::IsWindow(hWndCtrl
أولا nID لا تساوي الصفر و IsWindow أرجعت FALSE لأن القيمة كما ذكرت خاطئة ..

أكيد عندما تصنع نسخة Release من البرنامج فإن المشكلة لن تظهر لأن Assert لا تعمل في الRelease ، ولكن المشكلة تبقى موجودة ، ولا تستطيع أن تلتقط الرسالة ذات القيم EN_ALIGN_LTR أو EN_ALIGN_RTL . إذا أردت أيضا في نسخة الDebug أن تذهب المشكلة فأضف الكود التالي إلى OnCommand في CMainFrame :
CODE2

BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
{
#ifdef _DEBUG
if (HIWORD(lParam) == EN_ALIGN_LTR ||
HIWORD(lParam) == EN_ALIGN_RTL)
{
return TRUE;
}
#endif

return CFrameWnd::OnCommand(wParam, lParam);
}

تلاحظ من الكود في الأعلى أن في حالة كانت قيمة الWord العلوي من lParam هي أحد قيمتي الNotification فإننا نرجع TRUE وهذا يعني أننا نفذنا الرسالة و تتوقف Message Routing عن الإستمرار . (لاحظ أن الكود في الأعلى يعمل في ال Debug فقط)

الحل الآخر :
وهو طبعا أفضل ، لأنه ينهي جميع المشاكل المتعلقة بال RichEdit أو بالأصح RichEdit v1.0 . إن CRichEditView و CRichEditCtrl كلاهما يستخدمان RichEdit v1.0 الموجود في المكتبة Riched32.dll. في الحقيقة يوجد مع الويندوز نسخة أحدث من تلك وهي الإصدار الثالث V3.0 وهي في الملف Riched20.dll . ومن أجل إستخدامها في MFC بدلا من ال RichEdit القياسية يجب أن تعمل لفة بسيطة .. لقت قمت ببرمجة Class جديد موروث من CRichEditView سميته بـ CrichEditViewEx ، وقد إستفدت من كود ال MFC كثيرا في برمجته . الفرق الوحيد بينهما أن الثاني يستخدم ال RichEditv3.0 بدلا من RichEditv1.0 أي يقوم بتحميل مكتبة مختلفة عند الإنشاء . وهناك فروقات أخرى تمنحك إياها RichEdit الجديدة بسبب التحسينات التي فيها .. أحد هذه التحسينات هو إمكانية تحسس عنوان ال URL أثناء الكتابة ، وتمنحك Notifications جديدة من أجل استخدام هذا ال URL .
من أجل استخدامها ، فقط أضف ملفا ال CPP و الH إلى مشروعك وقم باستبدال أي CRichEditView ب CRichEditViewEx .. وسوف تلاحظ أن مشكلة ال Ctrl+Shift قد حلت في هذه النسخة الجديدة من الRichEdit .

CRichEditViewEx : وضعته لك في الوصلة التالية : http://haniproxy.netfirms.com/RichEditViewEx.zip

وأنا منتظرك أن تجربه وتعطيني ملاحظاتك ..
bozoclown2000
السلام عليكم و رحمة الله و بركاته

أخ هاني

لقد تم تعديل الملف ووضع نسخة realese أتمنى أن تجرب البرنامج و تعطيني انطباعاتك ..
و سوف أقوم لاحقا ان شاء الله بتجربة الكلاس الجديدة ..

شكرا لك
هاني الأتاسي
السلام عليكم،

آسف على تأخري في الرد عليك ، وذلك بسبب وجود مشاكل في جهازي للوصول للإنترنيت . للأمس حتى استطعت تنزيل البرنامج .

البرنامج جيد ومشكور على الجهد الذي بذلته من أجل إخراجه على الصورة الحالية . ولكن في الحقيقة لدي بعض الملاحظات :
  • هناك مشاكل في كتابة الأحرف فأحيانا لا يتحسس البرنامج كبسات الأحرف الصحيحة . ونادرا ما يتحسس عندما أضغط الستة أحرف مع بعضها .. إذا لم يكن هناك مانع لديك ، هل بالإمكان أن تطرح خوارزميتك في معالجة الكبسات وممكن نتناقش ، وإن شاء الله تتحسن . وعلى كل أنا لدي طريقة أستخدم فيها OnIdle ، بس حابب بالأول إسمع طريقتك .
  • عند فتح ملف امتداده abr مسبق على الجهاز (مع العلم أنه ليس من إنتاج برنامجك) فإن برنامجك يقوم بفتحه وعرض مافه من رموز . ألم يكن بالأفضل وضع توقيع خاص لملفك يكتب في البداية ، يعرف عن طريقه هل الملف المراد فتحه هو فعلا ملف بيرل.
  • ال CView الأصفر الذي يظهر في الحروف المقابلة لحروف بيرل أليس من الفضل أن يكون CEditView أو CRichEditView ، حتى تعطي المستخدم مرونة أكثر في الإستخدام . أي يستطيع الكتابة في النافذتين .
  • برنامجك واجهتة كلها معكوسة إلى جهة اليمين (عربي) ولكن لماذا بقيت ال ToolBar إلى اليسار!!!


أرجو أن لا أكون قد أثقلت عليك بالملاحظات . وعلى كل هذه نقاط تحسين في البرنامج وليست لغلط في برنامجك أو ما شابه فالبرنامج متقن ، وبوركت .
bozoclown2000
السلام عليكم و رحمة الله و بركاته

أخي العزيز هاني الاتاسي يحفظه الله

لقد أثلج صدري ردك و تفاعلك مع رسالتي كثيرا .. فبارك الله فيك .. للعلم فقط يا أخ هاني أنا لم أبدأ في تعلم اللغة إلا من أربعة أشهر فقط .. بمعنى أنني لست محترفا في هذه اللغة فمنكم إن شاء الله نستفيد و نتعلم المزيد .. و الحمد لله أنني تعرفت على هذا المنتدى الرائع بحق .. و أتمنى فعلا أن نتعاون معا في تخريج برنامج يخدم إخواننا المكفوفين في العالم العربي أجمع .. أما بالنسبة للخوارزمية المتبعة في خلق التوافقية في ضغط مفاتيح لوحة المفاتيح فسأقوم بوضعها هنا و أتمنى أن تزودني بخوارزميتك التي ستكون إن شاء الله أفضل و أسرع ..
أما بالنسبة لقولك خلق توقيع خاص بملفات برايل فلم أفهم المقصود فأرجو إذا تكرمت توضيح ذلك لي ..

CODE2

enum
{
keyD = 0x0001, // bit 0 - key D is down
keyF = 0x0002, // bit 1 - key F is down
keyG = 0x0004, // bit 2 - key G is down
keyJ = 0x0008, // bit 3 - key J is down
keyK = 0x0010, // bit 4 - key K is down
keyL = 0x0020 // bit 5 - key L is down
};
enum
{
vkeycodeD = 0x44,
vkeycodeF = 0x46,
vkeycodeG = 0x47,
vkeycodeJ = 0x4A,
vkeycodeK = 0x4B,
vkeycodeL = 0x4C
};
typedef map KeyMap;
typedef KeyMap::iterator KeyIter;


// exView.cpp : implementation of the CExView class
//

#include "stdafx.h"
#include "ex.h"

#include "exDoc.h"
#include "CntrItem.h"
#include "exView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CExView

IMPLEMENT_DYNCREATE(CExView, CRichEditView)

BEGIN_MESSAGE_MAP(CExView, CRichEditView)
//{{AFX_MSG_MAP(CExView)
ON_WM_DESTROY()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_WM_CHAR()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CRichEditView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CRichEditView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CRichEditView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExView construction/destruction

CExView::CExView()
{
// TODO: add construction code here

m_keyMap[keyF] = 'a'; // alef
m_keyMap[keyF|keyD] = 'b'; //baa
m_keyMap[keyD|keyS|keyJ|keyK] = 't'; // taa
m_keyMap[keyF|keyJ|keyK|keyL] = '?'; //tha
m_keyMap[keyD|keyJ|keyK] = 'j'; // jim
m_keyMap[keyF|keyK|keyL] = ':'; //7a
m_keyMap[keyF|keyS|keyJ|keyL] = 'x'; //kha
m_keyMap[keyF|keyJ|keyK] = 'd'; //dal
m_keyMap[keyD|keyS|keyJ|keyL] = '!';//thal
m_keyMap[keyF|keyD|keyS|keyK] = 'r'; //raa
m_keyMap[keyF|keyS|keyK|keyL] = 'z'; //zai
m_keyMap[keyD|keyS|keyJ] = 's'; //sin
m_keyMap[keyF|keyJ|keyL] = '%'; //shin
m_keyMap[keyF|keyD|keyS|keyJ|keyL] = '&'; //ssad
m_keyMap[keyF|keyD|keyJ|keyL] = '$'; //ddad
m_keyMap[keyD|keyS|keyJ|keyK|keyL] = ')'; //ta`
m_keyMap[keyF|keyD|keyS|keyJ|keyK|keyL] = '='; //dha`
m_keyMap[keyF|keyD|keyS|keyK|keyL] = '('; //ain
m_keyMap[keyF|keyD|keyL] = '<'; //ghain
m_keyMap[keyF|keyD|keyJ] = 'f'; //fa
m_keyMap[keyF|keyD|keyS|keyJ|keyK] = 'q'; //gaf
m_keyMap[keyF|keyS] = 'k'; //kaf
m_keyMap[keyF|keyD|keyS] = 'l'; //lam
m_keyMap[keyF|keyS|keyJ] = 'm'; //mim
m_keyMap[keyF|keyS|keyJ|keyK] = 'n'; //nun
m_keyMap[keyF|keyD|keyK] = 'h'; //ha
m_keyMap[keyD|keyJ|keyK|keyL] = 'w'; //waw
m_keyMap[keyD|keyJ] = 'i'; //yea


}

CExView::~CExView()
{
}

BOOL CExView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs

return CRichEditView::PreCreateWindow(cs);
}

void CExView::OnInitialUpdate()
{
CRichEditView::OnInitialUpdate();

CHARFORMAT cf;
cf.cbSize = sizeof (CHARFORMAT);
cf.dwMask = CFM_SIZE|CFM_FACE;
cf.dwEffects=0;
cf.yHeight=300;

::lstrcpy (cf.szFaceName, "SimBraille");
CRichEditView::SetCharFormat (cf);
// Set the printing margins (720 twips = 1/2 inch).
SetMargins(CRect(720, 720, 720, 720));
}

/////////////////////////////////////////////////////////////////////////////
// CExView printing

BOOL CExView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}


void CExView::OnDestroy()
{
// Deactivate the item on destruction; this is important
// when a splitter view is being used.
CRichEditView::OnDestroy();
COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
if (pActiveItem != NULL && pActiveItem->GetActiveView() == this)
{
pActiveItem->Deactivate();
ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
}
}


/////////////////////////////////////////////////////////////////////////////
// CExView diagnostics

#ifdef _DEBUG
void CExView::AssertValid() const
{
CRichEditView::AssertValid();
}

void CExView::Dump(CDumpContext& dc) const
{
CRichEditView::Dump(dc);
}

CExDoc* CExView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CExDoc)));
return (CExDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CExView message handlers


BOOL CExView::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class

return CRichEditView::PreTranslateMessage(pMsg);
}



void CExView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default

switch ( nChar )
{
case vkeycodeD: m_nKeyFlags|=keyD; m_nKeyCnt++; m_fInProcess=TRUE; break;
case vkeycodeF: m_nKeyFlags|=keyF; m_nKeyCnt++; m_fInProcess=TRUE; break;
case vkeycodeJ: m_nKeyFlags|=keyJ; m_nKeyCnt++; m_fInProcess=TRUE; break;
case vkeycodeK: m_nKeyFlags|=keyK; m_nKeyCnt++; m_fInProcess=TRUE; break;
case vkeycodeL: m_nKeyFlags|=keyL; m_nKeyCnt++; m_fInProcess=TRUE; break;
case vkeycodeS: m_nKeyFlags|=keyS; m_nKeyCnt++; m_fInProcess=TRUE; break;
case 'b':
case 't':
case 'r':
case 'n':
case ' ':
CRichEditView::OnKeyDown(nChar, nRepCnt, nFlags);
break;
default:
MessageBeep( MB_ICONASTERISK ); // error
m_nKeyFlags= 0; // start fresh for next key
m_fInProcess= FALSE;
m_nKeyCnt= 0;
return;
}


//CRichEditView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CExView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default

m_nKeyCnt--;
if ( m_fInProcess && (m_nKeyCnt <= 0) ) {
DoAction(); // decode flag bit to a letter and display it
m_nKeyFlags= 0; // start fresh for next key
m_fInProcess= FALSE;
m_nKeyCnt= 0;
}


//CRichEditView::OnKeyUp(nChar, nRepCnt, nFlags);
}


void CExView::DoAction()
{

KeyIter itFound = m_keyMap.find (m_nKeyFlags);
KeyIter itEnd= m_keyMap.end();

if ( itFound == itEnd ){
MessageBeep( MB_ICONASTERISK ); // error
return; // No action registered for a specified key
}


char chAction = (*itFound).second;

// Do the action
// e.g. send WM_CHAR
DefWindowProc(WM_CHAR, chAction, 0);

}

void CExView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
switch (nChar)
{
case 'b': // backspace
CView::OnChar(nChar,nRepCnt,nFlags);
break ;

case 't': // tab
CView::OnChar(nChar,nRepCnt,nFlags);
break ;

case 'n': // line feed
CView::OnChar(nChar,nRepCnt,nFlags);
break ;

case 'r': // carriage return
CView::OnChar(nChar,nRepCnt,nFlags);
break ;

case ' ': // Space key
CView::OnChar(nChar,nRepCnt,nFlags);
break ;


default: // character codes
if ((toupper(nChar)=='F') ||(toupper(nChar)=='D')
|| (toupper(nChar)=='S') || (toupper(nChar)=='J')
|| (toupper(nChar)=='K') || (toupper(nChar)=='L'))
{
// don't do anything this is used to block unwanted charecters
}
}
//CRichEditView::OnChar(nChar, nRepCnt, nFlags);
}
هذه "نسخة - خفيفة" من محتويات الرئيسية للإستعراض الكامل مع المزيد من الصور والخيارات الرجاء إضغط هنا.
Invision Power Board © 2001-2009 Invision Power Services, Inc.